vue实现直播间点赞飘心效果的示例代码


Posted in Javascript onSeptember 20, 2019

前言:

在开发公司项目的时候,遇到了直播间的一些功能,其中点赞冒泡飘心,就折腾了好久,canvas学的不好,自己写不来,百度找了一堆都是js原生写法,迁移到vue项目里来好多问题,百度也解决不了。自己试着慢慢解决,竟然在不知不觉中通了!废话不多说,直接上代码,复制粘贴即可使用

示例:

vue实现直播间点赞飘心效果的示例代码

不动就不动吧.png

```第一步```:先在外部新建一个js文件,取名index.js(名字自己随便取)

index.js代码内容如下:

/**
 * LikeHeart
 * @version: 1.0.0
 * @author tennylv
 * @date 2018-05-24
 *
 */
'use strict';
(function (root, factory) {
  if (typeof exports === 'object') {
    module.exports = factory();
    //CMD
  } else if (typeof define === 'function' && define.amd) {
    define(factory);
    //AMD
  } else {
    //WINDOW
    root.LikeHeart = factory(); 
  }
})(this, function() {

  var LikeHeart = function(opt) {

    /**
     * 初始化心
     * 
     * @param {object} 
     * @object.x {number} 心起点位置x
     * @object.y {number} 心起点位置y
     * @object.endX {number} 心结束位置x
     * @object.endY {number} 心结束位置y
     * @object.height {number} 高
     * @object.width {number} 宽
     * @object.angelBegin {number} 左右摇摆起始角度(可为负值)
     * @object.angelEnd {number} 左右摇摆结束角度
     * @object.angleLeft {bool} 是否起始从坐往右摇摆
     * @object.noScale {bool} 是否使用缩放心动画
     * @object.scaleDis {number} 缩放心临界值(默认从起始位置到升高50)
     * @object.noFadeOut {bool} 是否使用fadeOut
     * @object.opacityDis {number} fadeout心临界值(默认距离结束位置40)
     * @object.speed {number} 上升速度 
     * @object.bezierPoint {obj} 贝塞尔曲线4个点的值参考https://aaaaaaaty.github.io/bezierMaker.js/playground/playground.html
     * @object.fadeOut {function} 每个心fadeOut之后回调
     * @object.image {obj} 图片对象
     */


     this.id = opt.id;
     this.x = opt.x;
     this.y = opt.y;
     this.endX = opt.endX;
     this.endY = opt.endY;
     this.orignY = opt.y;
     this.height = opt.height;
     this.width = opt.width;
     this.angle = 0;
     this.angleLeft = opt.angleLeft;
     this.angelBegin = opt.angelBegin || (-20 + rand(1,2));
     this.angelEnd = opt.angelEnd || (20 + rand(1,4));
     this.scale = 0;
     this.scaleDis = opt.scaleDis || 50;
     this.opacityDis = opt.opacityDis || 40;
     this.noScale = opt.noScale;
     this.noAngel = opt.noAngel;
     this.opacity = 1;
     this.speed = opt.speed || 0.0027;
     this.bezierPoint = opt.bezierPoint;
     this.bezierDis = 0;
     this.onFadeOut = opt.onFadeOut;
     this.IMG = opt.image;

     this.move = function (ctx) {

      if (this.opacity === 0) {

        this.onFadeOut && this.onFadeOut(this);
      }

      this.y = getBezierLine(this).yt;
      this.x = getBezierLine(this).xt;


      this.angle = rangeAngle(this);
      this.scale = getFScale(this);
      this.opacity = getFAlpha(this);


      ctx.save();
      ctx.translate(this.x, this.y);
      ctx.rotate(this.angle*(Math.PI/180));
      ctx.scale(this.scale, this.scale);
      ctx.globalAlpha = this.opacity;

      ctx.drawImage(this.IMG, -(this.IMG.width/2), -(this.IMG.height/2), this.width, this.height);
      ctx.restore();
     };

  };


  /**
   * 计算心左右摇摆的方法
   */
  function rangeAngle(heart) {
    if (heart.noAngel) {
      return 0;
    }
    let _angle = heart.angle;

    // 心介于[start, end]之间不断变化角度
    if(_angle >= heart.angelEnd) {
      // 角度不断变小,向左摇摆
      heart.angleLeft = false;
    } else if (_angle <= heart.angelBegin){
      // 角度不断变大,向又摇摆
      heart.angleLeft = true;
    }

    // 动态改变角度
    if (heart.angleLeft) {
      _angle = _angle + 1;
    } else {
      _angle = _angle - 1;
    }

    return _angle;

  }


  /**
   * 计算缩放角度的方法
   */
  function getFScale(heart){
    if (heart.noScale) {
      return 1;
    }
    let _scale = heart.scale;


    // 随着距离起始点的距离增加,scale不断变大
    let dis = heart.orignY - heart.y;
    _scale = (dis / heart.scaleDis);

    // 当大于设置的阈值时变成1
    if (dis >= heart.scaleDis) {
      _scale = 1;
    }

    return _scale;
  }

  /**
   * 计算透明度的方法
   */
  function getFAlpha(heart) {

    let _opacity = heart.opacity;

    let dis = heart.y - heart.endY;

    if (dis <= heart.opacityDis) {

      _opacity = Math.max((dis / heart.opacityDis), 0);

    } else {
      _opacity = 1;
    }
    return _opacity;
  }

  /**
   * 获得min-max的随机整数
   */
  function rand (min, max) {
   return Math.floor(Math.random() * (max - min + 1)) + min;
  }

  /**
   * 获得贝塞尔曲线路径
   * 一共4个点
   */
  function getBezierLine(heart){
    var obj = heart.bezierPoint;
    var p0 = obj.p0;
    var p1 = obj.p1;
    var p2 = obj.p2;
    var p3 = obj.p3;
    var t = heart.bezierDis;
    var cx = 3 * (p1.x - p0.x),
      bx = 3 * (p2.x - p1.x) - cx,
      ax = p3.x - p0.x - cx - bx,

      cy = 3 * (p1.y - p0.y),
      by = 3 * (p2.y - p1.y) - cy,
      ay = p3.y - p0.y - cy - by,

      xt = ax * (t * t * t) + bx * (t * t) + cx * t + p0.x,
      yt = ay * (t * t * t) + by * (t * t) + cy * t + p0.y;

    heart.bezierDis += heart.speed;

    return {
      xt: xt,
      yt: yt
    }
  }

  return LikeHeart;

});
```第二步```:引入需要用到的页面
import LikeHeart from "../../../static/js/index";
```第三步```:直接复制下面这一段
<script>
import LikeHeart from "../../../static/js/index";
export default {
 props: ["ClassTimePlayer", "videoUrl"],
 data() {
  return {
   width: 175, //初始宽度
   height: 400, //初始高度
   heartList: [], //初始数组
   heartCount: 0 //累加计数初始值
  };
 },
 methods: {
  getRandomDis() {
   if (Math.random() > 0.5) {
    return -(Math.random() * 43);
   } else {
    return +(Math.random() * 43);
   }
  },
  createHeart() {
   this.heartCount++;
   let positionArray = [
    {
     x: 100,
     y: 400,
     endX: 100,
     endY: 100
    }
   ];
   let img = new Image();
   // img.src = "../../static/img/" + Math.ceil(Math.random() * 2) + ".png";
   img.src = `../../static/img/${Math.ceil(Math.random() * 5)}.png`;
   let p1 = {
    x: 100 + this.getRandomDis(),
    y: 300 + this.getRandomDis()
   };
   let p2 = {
    x: 100 + this.getRandomDis(),
    y: 200 + this.getRandomDis()
   };
   return new LikeHeart({
    id: this.heartCount,
    x: positionArray[0].x,
    y: positionArray[0].y,
    endX: positionArray[0].endX,
    endY: positionArray[0].endY,
    onFadeOut: this.removeItem,
    noAngel: true,//决定是否从小到大
    // noScale: true,//决定是否左右摆动
    width: 30, //决定心的大小
    height: 30,
    image: img,
    bezierPoint: {
     p0: {
      x: positionArray[0].x,
      y: positionArray[0].y
     },
     p1: p1,
     p2: p2,
     p3: {
      x: positionArray[0].endX,
      y: positionArray[0].endY
     }
    }
   });
  },
  removeItem(item) {
   var array = [];
   for (var i = 0; i < this.heartList.length; i++) {
    if (this.heartList[i].id !== item.id) {
     array.push(this.heartList[i]);
    }
   }
   this.heartList = array;
  },
  },

  
  
 
 mounted() {
  // 飘心
  var _this = this;
  var ctx = document.getElementById("cvs").getContext("2d");
  (ctx.canvas.width = _this.width),
   (ctx.canvas.height = _this.height),
   (function loop() {
    ctx.clearRect(0, 0, _this.width, _this.height);
    _this.heartList.forEach(function(item) {
     item && item.move(ctx);
    });
    requestAnimationFrame(loop);
   })();
  setInterval(function() {
   _this.heartList.push(_this.createHeart());
  }, 700);
  document.getElementById("cvs").addEventListener(
   "click",
   function() {
    console.log(111111)
    _this.heartList.push(_this.createHeart());
   },
   false
  );
 },
};
</script>
图片自己去换,至于在哪里换 
img.src = `../../static/img/${Math.ceil(Math.random() * 5)}.png`;
这个就是咯
 ```最后一步```:在html里,写上这个 
  <!-- 飘心 -->
  <canvas id="cvs"></canvas>

收尾:

然后就实现了。这个代码我也是百度的某个大神的,最后说明下不是我写的哈。迁移到vue中稍微修改了一下,勿喷。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
学习YUI.Ext 第六天--关于树TreePanel(Part 1)
Mar 10 Javascript
javascript 广告后加载,加载完页面再加载广告
Nov 25 Javascript
jQuery对于显示和隐藏等常用状态的判断方法
Dec 13 Javascript
jquery滚动到顶部底部代码
Apr 20 Javascript
Node.js的MongoDB驱动Mongoose基本使用教程
Mar 01 Javascript
jQuery侧边栏实现代码
May 06 Javascript
详解JavaScript实现设计模式中的适配器模式的方法
May 18 Javascript
jQuery中$.grep() 过滤函数 数组过滤
Nov 22 Javascript
vue 实现 tomato timer(蕃茄钟)实例讲解
Jul 24 Javascript
详解Vue.js v-for不支持IE9的解决方法
Dec 29 Javascript
详解如何给React-Router添加路由页面切换时的过渡动画
Apr 25 Javascript
JS造成内存泄漏的几种情况实例分析
Mar 02 Javascript
vue+layui实现select动态加载后台数据的例子
Sep 20 #Javascript
layui 中select下拉change事件失效的解决方法
Sep 20 #Javascript
微信小程序实现打开并下载服务器上面的pdf文件到手机
Sep 20 #Javascript
在layui框架中select下拉框监听更改事件的例子
Sep 20 #Javascript
关于layui 下拉列表的change事件详解
Sep 20 #Javascript
刷新页面后让控制台的js代码继续执行
Sep 20 #Javascript
layui动态绑定事件的方法
Sep 20 #Javascript
You might like
浅析虚拟主机服务器php fsockopen函数被禁用的解决办法
2013/08/07 PHP
PHP使用递归算法无限遍历数组示例
2017/01/13 PHP
PHP页面静态化――纯静态与伪静态用法详解
2020/06/05 PHP
jquery nth-child()选择器的简单应用
2010/07/10 Javascript
jQuery中filter()和find()的区别深入了解
2013/09/25 Javascript
jquery数组之存放checkbox全选值示例代码
2013/12/20 Javascript
jquery实现select选中行、列合计示例
2014/04/25 Javascript
jQuery中slideUp 和 slideDown 的点击事件
2015/02/26 Javascript
WordPress 单页面上一页下一页的实现方法【附代码】
2016/03/10 Javascript
基于BootStrap实现简洁注册界面
2017/07/20 Javascript
浅谈react-router HashRouter和BrowserRouter的使用
2017/12/29 Javascript
vue.js使用v-if实现显示与隐藏功能示例
2018/07/06 Javascript
JS Object.preventExtensions(),Object.seal()与Object.freeze()用法实例分析
2018/08/25 Javascript
Vue 组件封装 并使用 NPM 发布的教程
2018/09/30 Javascript
mock.js实现模拟生成假数据功能示例
2019/01/15 Javascript
微信小程序导入Vant报错VM292:1 thirdScriptError的解决方法
2019/08/01 Javascript
Vue实现开心消消乐游戏算法
2019/10/22 Javascript
Node对CommonJS的模块规范
2019/11/06 Javascript
解决vant中 tab栏遇到的坑 van-tabs
2020/11/04 Javascript
[52:29]DOTA2上海特级锦标赛主赛事日 - 2 胜者组第一轮#3Secret VS OG第三局
2016/03/03 DOTA
[54:28]EG vs OG 2019国际邀请赛小组赛 BO2 第一场 8.16
2019/08/18 DOTA
介绍Python中的一些高级编程技巧
2015/04/02 Python
Python中绑定与未绑定的类方法用法分析
2016/04/29 Python
深入解析Python的Tornado框架中内置的模板引擎
2016/07/11 Python
python3使用pandas获取股票数据的方法
2018/12/22 Python
python3.6 如何将list存入txt后再读出list的方法
2019/07/02 Python
Python根据字典的值查询出对应的键的方法
2020/09/30 Python
python中altair可视化库实例用法
2021/01/26 Python
解锁canvas导出图片跨域的N种姿势小结
2019/01/24 HTML / CSS
adidas澳大利亚官方网站:adidas Australia
2018/04/15 全球购物
Spongelle官网:美国的创意护肤洗护品牌
2019/05/15 全球购物
Love, Bonito国际官网:新加坡女装品牌
2021/03/13 全球购物
宣传部部长竞选演讲稿
2014/04/26 职场文书
辞职信怎么写
2015/02/27 职场文书
工作年限证明模板
2015/06/15 职场文书
大学学生会主席竞选稿怎么写?
2019/08/19 职场文书