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 相关文章推荐
JS日历 推荐
Dec 03 Javascript
Javascript 面向对象 对象(Object)
May 13 Javascript
jQuery教程 $()包装函数来实现数组元素分页效果
Aug 13 Javascript
jQuery 1.9移除了$.browser可以使用$.support来替代
Sep 03 Javascript
javascript trim函数在IE下不能用的解决方法
Sep 12 Javascript
关于数据与后端进行交流匹配(点亮星星)
Aug 03 Javascript
Jquery Easyui表单组件Form使用详解(30)
Dec 19 Javascript
原生JavaScript实现精美的淘宝轮播图效果示例【附demo源码下载】
May 27 Javascript
bootstrap表格内容过长时用省略号表示的解决方法
Nov 21 Javascript
Node中使用ES6语法的基础教程
Jan 05 Javascript
Vue循环遍历选项赋值到对应控件的实现方法
Jun 22 Javascript
VsCode里的Vue模板的实现
Aug 12 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
全国FM电台频率大全 - 28 甘肃省
2020/03/11 无线电
PHP 利用Mail_MimeDecode类提取邮件信息示例
2014/01/26 PHP
PHP的拦截器实例分析
2014/11/03 PHP
php微信公众号js-sdk开发应用
2016/11/28 PHP
一个javascript参数的小问题
2008/03/02 Javascript
javascript通过navigator.userAgent识别各种浏览器
2013/10/25 Javascript
深入理解jQuery中live与bind方法的区别
2013/12/18 Javascript
JavaScript学习笔记之DOM基础 2.4
2015/08/14 Javascript
轻松学习jQuery插件EasyUI EasyUI表单验证
2015/12/01 Javascript
javascript图片切换综合实例(循环切换、顺序切换)
2016/01/13 Javascript
javascript中错误使用var造成undefined
2016/03/31 Javascript
AngularJs用户登录问题处理(交互及验证、阻止FQ处理)
2017/10/26 Javascript
Thinkjs3新手入门之添加一个新的页面
2017/12/06 Javascript
vue中实现左右联动的效果
2018/06/22 Javascript
解决vue A对象赋值给B对象,修改B属性会影响到A的问题
2018/09/25 Javascript
python每次处理固定个数的字符的方法总结
2013/01/29 Python
举例讲解Python编程中对线程锁的使用
2016/07/12 Python
Python多继承顺序实例分析
2018/05/26 Python
Python 使用类写装饰器的小技巧
2018/09/30 Python
Python实现的特征提取操作示例
2018/12/03 Python
python爬虫scrapy基本使用超详细教程
2021/02/20 Python
HTML5 移动页面自适应手机屏幕四类方法总结
2017/08/17 HTML / CSS
HTML5添加禁止缩放功能
2017/11/03 HTML / CSS
墨尔本复古时尚品牌:Dangerfield
2018/12/12 全球购物
为什么要做架构设计
2015/07/08 面试题
制药工程专业毕业生推荐信
2013/12/24 职场文书
机关门卫制度
2014/02/01 职场文书
公司端午节活动方案
2014/02/04 职场文书
元宵晚会主持词
2014/03/25 职场文书
公司应聘求职信
2014/06/21 职场文书
群众路线教育实践活动学习心得体会
2014/10/30 职场文书
护士2015年终工作总结
2015/04/29 职场文书
学习型家庭事迹材料(2016精选版)
2016/02/29 职场文书
Java练习之潜艇小游戏的实现
2022/03/16 Java/Android
SpringBoot2零基础到精通之数据库专项精讲
2022/03/22 Java/Android
Python图像处理库PIL详细使用说明
2022/04/06 Python