资讯专栏INFORMATION COLUMN

Vue - 组件开发和实例旋转轮盘

shiyang6017 / 2907人阅读

摘要:请教本来设想的是通过来传递卡片的内部结构和数组数据,例如传递一个渲染函数,通过可以轻松的实现但是这招行不通。

使用 vue 编写的一个可旋转组件,如图

demo地址: https://github.com/tanf1995/m...

布局

用卡片数量均分360度圆,使用绝对定位分布在外部容器上,自身通过rotate旋转

       computedCardPosStyle(index){
       let deg = index * this.unitCardDeg;
       let absDeg = Math.abs((deg + this.turnRotate) % 360);
       let z_index = absDeg > 180 ? Math.ceil(absDeg-180): Math.ceil(180-absDeg);

       return {
           width: this.cardWidth + "px",
           height: this.cardHeight + "px",
           top: -Math.cos(deg*Math.PI/180)*this.turntableR + "px",
           left: Math.sin(deg*Math.PI/180)*this.turntableR + "px",
           transform: `translate(-50%, -50%) rotate(${deg}deg)`,
           zIndex: z_index
       }
   },
   

外部容器定位于浏览器窗口之下,露出正上方部分出来

   
...

圆盘的转动

onmousedown、onmouseup 用来判断鼠标是否处于按下状态,并且清空上一次拖动的数据

圆盘的转动以横向滑动的总距离更新角度

针对圆盘如何转动,设计按每一个小的间隔时间(如20ms),叠加一次总体滑动的距离

handleMouseDown(e){
    e.preventDefault();
    clearInterval(this.UDLMactionTimer);
    this.mouseIsDown = true;
    this.startX = e.clientX || e.touches[0].clientX;
    this.endX = e.clientX || e.touches[0].clientX;
},
handleMouseUp(e){
    e.preventDefault();
    this.mouseIsDown = false;
    clearInterval(this.timer);
    clearInterval(this.UDLMactionTimer);
    this.timer = null;
    this.startX = 0;
    this.endX = 0;
    if(this.lastSpeed) this.UDLMaction();
},
handleMouseMove(e){
    e.preventDefault();
    this.endX = e.clientX || e.touches[0].clientX;
    if(!this.mouseIsDown) return;
    if(!this.timer){
        this.timer = setInterval(() => {
            let moveGap = this.endX - this.startX;

            this.lastSpeed = moveGap/this.timeGap;
            this.xGap += moveGap;
            this.direction = moveGap > 0 ? 1 : -1;
            this.startX = this.endX;
        }, this.timeGap);
    }
},

mounted(){
let container_dom = this.outerWrap ? this.$refs.outerWrap : this.$refs.container;

container_dom.addEventListener("mousedown", this.handleMouseDown.bind(this));
container_dom.addEventListener("mouseup", this.handleMouseUp.bind(this));
container_dom.addEventListener("mouseleave", this.handleMouseUp.bind(this));
container_dom.addEventListener("mousemove", this.handleMouseMove.bind(this));
container_dom.addEventListener("touchstart", this.handleMouseDown.bind(this));
container_dom.addEventListener("touchend", this.handleMouseUp.bind(this));
container_dom.addEventListener("touchcancel", this.handleMouseUp.bind(this));
container_dom.addEventListener("touchmove", this.handleMouseMove.bind(this));

window.addEventListener("resize", this.responseContainerScale.bind(this));
window.addEventListener("load", this.responseContainerScale.bind(this));
},
beforeDestroy(){
    let container_dom = this.outerWrap ? this.$refs.outerWrap : this.$refs.container;

    container_dom.removeEventListener("mousedown", this.handleMouseDown.bind(this));
    container_dom.removeEventListener("mouseup", this.handleMouseUp.bind(this));
    container_dom.removeEventListener("mouseleave", this.handleMouseUp.bind(this));
    container_dom.removeEventListener("mousemove", this.handleMouseMove.bind(this));
    container_dom.removeEventListener("touchstart", this.handleMouseDown.bind(this));
    container_dom.removeEventListener("touchend", this.handleMouseUp.bind(this));
    container_dom.removeEventListener("touchcancel", this.handleMouseUp.bind(this));
    container_dom.removeEventListener("touchmove", this.handleMouseMove.bind(this));

    window.removeEventListener("resize", this.responseContainerScale.bind(this));
}

旋转效果平滑

如果没有滑动惯性,当滑动完之后,无论滑动的时候速度如何的快,在松开鼠标后转盘立刻停下,使得效果非常生硬。所以在滑动完成之后,利用最后时刻的滑动速度,让转盘做匀减速运动直至速度为0,并且在速度为0时,在设计缓慢细小的匀速滑动,最后呈现出来的效果就比较平滑了。

UDLMaction(){

   let a = -this.reduceSpeed*this.direction;
   this.UDLMactionTimer = setInterval(() => {
       this.lastSpeed = (this.lastSpeed + a)*this.direction >= 0? this.lastSpeed + a: 0;
       this.xGap += (this.lastSpeed) * this.timeGap;
       if(!this.lastSpeed){
           this.moreDynamic();
           return clearInterval(this.UDLMactionTimer);
       }
   }, this.timeGap);

},
moreDynamic(){

   let time = 10;
   let timer = setInterval(() => {
       this.xGap += this.direction*3;
       if(--time <= 0) clearInterval(timer);
   }, 20)

},

请教

本来设想的是通过prop来传递卡片的内部结构和数组数据,例如传递一个渲染函数,通过react可以轻松的实现,但是vue这招行不通。请问如何能够做到这点呢?react伪代码如下

 }
>

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/109919.html

相关文章

  • vue2.6实现一个抖音很火的【时间轮盘】屏保小DEMO

    摘要:代码如下转动然后通过具体的秒分小时上下午星期日期月值转动,来控制角度,而且当前值进行文字高亮。 写在前面:前段时间看抖音,有人用时间轮盘作为动态的桌面壁纸,一时间成为全网最火的电脑屏保,后来小米等运用市场也出现了【时间轮盘】,有点像五行八卦,感觉很好玩,于是突发奇想,自己写一个网页版小DEMO玩玩,先看看效果:在线体验showImg(https://user-gold-cdn.xitu.io...

    wind5o 评论0 收藏0
  • Vue+CSS3实现转盘抽奖

    摘要:最近有个转盘抽奖的需求,搜了一下现有的轮子,有的是用的动画函数实现的,有的是用绘图然后再用高频率的调用旋转方法,前者太老了没法简单移植到项目,后者感觉性能表现可能不会太好。核心思路是用以及实现旋转动画,使用和绘制出定位较为精确的轮盘奖项。 最近有个转盘抽奖的需求,搜了一下现有的轮子,有的是用jQuery的动画函数实现的,有的是用canvas绘图然后再用高频率的setTimeout调用旋...

    mj 评论0 收藏0
  • [phaser3学习]使用phaser3做一款飞刀小游戏

    摘要:前言作为一款流行的游戏动画框架受到很多开发者的青睐最近笔者在逛意大利开发者论坛的时候发现了这款小游戏所以就照着说明做了一下在这里记录下来开发准备插件脚本飞刀和靶子的图像或者这个项目里面有的脚本和需要的图像文件开始制作搭建基本的项目创建一个 前言 phaser作为一款流行的游戏/动画框架,受到很多web开发者的青睐,最近笔者在逛意大利开发者:emanueleferonato论坛的时候发现...

    BothEyes1993 评论0 收藏0
  • 百度地图开发实例番外篇--实用方法(持续更新)

    摘要:一前言在使用百度地图开发的过程中,查阅百度地图官网基本上就能满足开发的需求,但是有时候需要设置一些东西,很难在官网上查阅到相关的方法技巧。希望百度地图能够越来越强大,这样开发者就可以愉快的开发了 一 前言 在使用百度地图开发的过程中,查阅百度地图官网demo基本上就能满足开发的需求,但是有时候需要设置一些东西,很难在官网上查阅到相关的方法技巧。笔者特意把开发过程中遇到的一些疑难杂症和解...

    CocoaChina 评论0 收藏0
  • 前端知识归纳

    摘要:继承性子标签会继承父标签样式优先级行内样式选择器类选择器标签选择器通配符继承机制创建了的元素中,在垂直方向上的会发生重叠。 技能考察: 一、关于Html 1、html语义化标签的理解; 结构化的理解; 能否写出简洁的html结构; SEO优化 a、理解:根据内容的结构化(内容语义化),选择合适的标签(代码语义化)便于开发者阅读和写出更优雅的代码的同时 让浏览器的爬虫和...

    sixleaves 评论0 收藏0

发表评论

0条评论

shiyang6017

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<