Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.9k views
in Technique[技术] by (71.8m points)

怎样减小运动时的抖动??

找的别人的代码 现在有个小问题 一个是运动时会有左右晃动 不想要这个晃动 或者晃动再小点 请问应该怎么改 对运动不是太了解 不知道如何下手 求大神帮忙看看
复制代码可以直接运行
image

<view class="index">
  <view class="wrapper" hidden="{{false}}" bindtouchmove="handletouchmove" bindtouchstart="handletouchstart">
      <view wx:for="{{tagEle}}" wx:key="{{key}}" wx:index="{{index}}" id="tag{{index}}" style="opacity:{{item.opacity}};top: {{item.top}};left: {{item.left}}; z-index: {{item.zIndex}};font-size: {{item.fontSize}}">
        <image class="icon" style="width: 100rpx;height: 100rpx;top:-100rpx;" wx:if="{{true}}" src="http://aigou-file.obs.cn-south-1.myhuaweicloud.com/images/5/2020/12/cstr00gX48ngG86NlMln6s4Ll1mlsB.png"></image>
        <text class="name2">{{item.title}}</text>
      </view>
  </view>
</view>
Page({
  data: {
    tagEle: [], // 标签标题数据
    tagState: true, // 是否显示标签云
    countTime: null, // 计算定时器
    lastX: 0, // 坐标X
    lastY: 0, // 坐标Y
    direction: 310, // 初始化标签词云角度,默认左上角
  }, 
  handletouchmove: function (event) {
    let currentX = event.touches[0].pageX // 获得X轴坐标
    let currentY = event.touches[0].pageY // 获得Y轴坐标
    let tx = currentX - this.data.lastX // 计算X轴偏差值
    let ty = currentY - this.data.lastY // 计算Y轴偏差值

    // 上下左右方向滑动
    if (tx === 0) { // 上下方向
      if (ty < 0) { // 上滑动
        this.data.direction = 360
      } else if (ty > 0) { // 下滑动
        this.data.direction = 180
      }
    } else if (ty === 0) { // 左右方向
      if (tx < 0) { // 左滑动
        this.data.direction = 270
      } else if (tx > 0) { // 右滑动
        this.data.direction = 90
      }
    } else if (tx < 0 && ty < 0) { // 左上滑动
      this.data.direction = 315
    } else if (tx < 0 && ty > 0) { // 左下滑动
      this.data.direction = 225
    } else if (tx > 0 && ty < 0) { // 右上滑动
      this.data.direction = 45
    } else if (tx > 0 && ty > 0) { // 右下滑动
      this.data.direction = 135
    } 

    // 将当前坐标进行保存以进行下一次计算
    this.data.lastX = currentX
    this.data.lastY = currentY
  },
  handletouchstart: function (event) {
    this.data.lastX = event.touches[0].pageX // 获得触摸点X轴坐标
    this.data.lastY = event.touches[0].pageY // 获得触摸点Y轴坐标
  }, 

  // 初始化标签云特效
  initialize(data) {
    const that = this
    let countList = [] // 计算列表数据集合
    let radius = 150 // 初始化滚动半径作用区域
    let tagEle = data // 标题元素数组
    this.setData({ // 首次赋值给到页面用于后续获取高宽值
      tagEle: tagEle
    })

    // 首次循环获取所有元素高宽值并计算得出首次计算列表数据
    for (let i = 0; i < tagEle.length; i++) {
      let query = wx.createSelectorQuery() // 小程序API获得组件对象
      query.select(`#tag${i}`).boundingClientRect(rect => { // 使用选择器获得每个id元素的高宽值
        let acos = Math.acos(-1 + (2 * i + 1) / tagEle.length) // 计算反余弦 
        let sqrt = Math.sqrt((tagEle.length + 1) * Math.PI) * acos // 计算平方根
        countList.push({
          offsetWidth: rect.width, // 当前id元素的宽度
          offsetHeight: rect.height, // 当前id元素的高度
          left: radius * 1.5 * Math.cos(sqrt) * Math.sin(acos), // 当前id元素的left值
          top: radius * 1.5 * Math.sin(sqrt) * Math.sin(acos), // 当前id元素的top值
          z: radius * 1.5 * Math.cos(acos), // 计算Z轴值
        })
      }).exec()
    }

    // 下列为主要运算赋值程序,定时器是由于小程序API获取高宽的异步执行,这里暂时没改为同步。即用定时器来做延时运行。
    setTimeout(() => {
      that.countTime = setInterval(() => {
        this.calculation(tagEle, countList, radius) // 调用计算函数
      }, 50) // 每50毫秒执行一次,考虑性能消耗问题,不建议更改时间,要控制速度更改ispeed值
      this.setData({
        tagState: false
      })
    }, 300)
  },
  // Style样式计算过程
  calculation(tagData, countData, num) {
    let countList = countData // 计算结果数组
    const radius = num // 滚动区域范围,默认单位为px,数值越大滚动范围越大
    let fontsize = 14 // 字体大小,默认单位为px,后期转换rem。数值越大字体越大
    let depth = 2 * radius // 滚动深度
    let ispeed = 15 // 滚动速度,数值越大滚动速度越快,不能小于2
    let direction = this.data.direction // 滚动方向, 取值角度(0-360): 0和360对应即从下到上, 90对应垂直X-Y,180对应从上倒下,其他数值随意测试...
    let directionX = ispeed * Math.sin(direction * Math.PI / 180) // 计算X轴Sin值
    let directioneY = -ispeed * Math.cos(direction * Math.PI / 180) // 计算Y轴Cos值
    let a = -(Math.min(Math.max(-directioneY, -radius), radius) / radius) * ispeed // 计算a值用以后续判断计算
    let b = (Math.min(Math.max(-directionX, -radius), radius) / radius) * ispeed // 计算b值用以后续判断计算
    let dtr = Math.PI / 180 // 计算圆周率
    let PIList = [ // 计算圆周率数组
      Math.sin(a * dtr),
      Math.cos(a * dtr),
      Math.sin(b * dtr),
      Math.cos(b * dtr)
    ]
    // 若ab值太小,即相关配置如速度/范围等太低,直接return不执行动效
    if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01) { return; }
    // 循环遍历每个元素前面所计算出来的各值
    for (let j = 0; j < countList.length; j++) {
      let rz1 = countList[j].top * PIList[0] + countList[j].z * PIList[1] // 计算前置数据
      let rz2 = rz1 * PIList[3] - countList[j].left * PIList[2] // 计算前置数据
      let per = depth / (depth + rz2) // 计算前置数据
      countList[j].left = countList[j].left * PIList[3] + rz1 * PIList[2] // 计算left用以后面计算赋值left
      countList[j].top = countList[j].top * PIList[1] + countList[j].z * (-PIList[0]) // 计算top用以后面计算赋值top
      countList[j].z = rz2 // 赋值计算列表中Z值新数据
      countList[j].fontsize = (per * 2 + fontsize) / 30 // 计算fontsize用以后面计算赋值font-size。注:最后除以30是用以后续rem单位计算,具体rem单位计算可参照官方计算。
      countList[j].alpha = 1.5 * per - 0.7 // 计算alpha用以后面计算赋值opacity
      countList[j].zIndex = Math.ceil(per * 10 - 5) // 计算zIndex用以后面计算赋值z-index
    }
    this.voluation(tagData, countList)
  },

  // Style样式赋值运算
  voluation(tagData, countData) {
    const tagEle = tagData
    const countList = countData
    let styleList = [] // 存储完整渲染列表的文字和样式结构
    for (let i = 0; i < countList.length; i++) {
      styleList.push({
        title: tagEle[i].title, // 标题文字内容
        left: countList[i].left + (500 - countList[i].offsetWidth) / 1.4 + "rpx",  // 500越大,则距离左边越远 
        top: countList[i].top + (450 - countList[i].offsetHeight) / 1.4 + "rpx", // 440越大,则距离上边越远
        zIndex: countList[i].zIndex, // z-index值
        opacity: countList[i].alpha,  // opacity值
        fontSize: countList[i].fontsize*0.9 + "rem", // font-size值。注:不采用rpx值是因为在小程序最后会被改为四舍五入后的px值,不支持小数点单位,在放大缩小中不是很美观。于是采用转换rem值。
        test: countList[i].top + (450 - countList[i].offsetHeight) / 2
      })
    }
    this.setData({ // 赋值给到页面渲染
      tagEle: styleList
    })
  },

  onLoad: function (options) {
    let tagEle = [ // 标题元素数组
      { title: '我是007' },  { title: '爱上大树的小猪' }, { title: '王者荣耀' }, { title: '伪程序猿' }, { title: '老人与代码' }, { title: '虚拟DOM' }, { title: 'CSS3不服' }, { title: 'Animation的锅' }, { title: '感谢先人踩的坑' }, { title: '后人接着挖点坑' }, { title: '博客园' }, { title: '复仇者联盟' }
    ]
    this.initialize(tagEle) // 调用标签云特效
  },

  onUnload() {
    clearInterval(this.countTime) // 清除计算定时器
    this.countTime = null // 清除计算定时器
  },
});
.index{
  width: 750rpx;
  height: 100vh;
  background-repeat:no-repeat;
  background-repeat:repeat-y;
  background-size:cover;
  background-position: center;
  background-color: black;
  display: flex;
  justify-content: center;
  align-items: center;
}
.logo{
  width: 185rpx;
  height: 48rpx;
  margin-top: 62rpx;
  margin-left: 32rpx;
}
.name{
  margin-left: 32rpx;
  margin-top: 30rpx;
  color: white;
}
page {
  width: 100%;
  height: auto;
}

.wrapper {
  width: 750rpx;
  position: relative;
  display: flex;
  min-height: 500rpx;
  background-color: #000000;
  justify-content: center;
  padding-top: 100rpx;
  padding-left: 100rpx;
  box-sizing: border-box;
}
.icon{
  border-radius: 60rpx;
  position: absolute;
}
.wrapper view {
  position: absolute;
  top: 60%;
  left: 40%;
  display: flex;
  flex-direction: column;
  padding: 11rpx 30rpx;
  color: #333;
  font-size: 20rpx;
  border: 1rpx solid #e6e7e8;
  border-radius: 18rpx;
  background-color: #f2f4f8;
  text-decoration: none;
  align-items: center;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
等待大神解答

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...