过年了,给你的浏览器也来一场烟火吧。

1,089 阅读5分钟

PK创意闹新春,我正在参加「春节创意投稿大赛」,详情请看:春节创意投稿大赛

马上就过年了,在这里提前祝大家新年快乐,虎年虎虎生威,如虎添翼。给你的浏览器也来一场烟火吧。

在这里插入图片描述 在这里插入图片描述

Chrome浏览器插件实现页面鼠标点击烟花效果

写在前面

效果如上图,鼠标点击之后页面会从底部发射一道烟花,在鼠标点击处绽放开来。

准备工作

1.了解浏览器插件制作方法

chrome扩展:manifest.json文件相关字段

2.实现方案

在网页上动态插入一个canvas元素,通过canvas来制作并展示烟花效果粒子,结合鼠标的点击事件,来触发烟花射线发射。

3.动手撸代码

minifest.json

简单地将必须的参数配置完整

{
    "name": "烟花点击特效",
    "version": "1.0.0",
    "manifest_version": 2,
    "description": "烟花点击特效",
    "browser_action": {
        "default_title": "查看",
        "default_icon": "1.jpg"
    },
    "content_scripts": [
        {
            "matches": ["<all_urls>"],
            "js": ["firework.js"]
        }
    ],
    "permissions" : ["tabs", "activeTab"] //向浏览器申请的权限
}

firework.js

1、创建canvas画布

在页面上插入一个canvas画布来实现动画效果展示。

let body = document.getElementsByTagName('body')[0];
let myCanvas = document.createElement('canvas');
myCanvas.id = 'canvas';
myCanvas.style.position = 'fixed';
myCanvas.style.left = '0';
myCanvas.style.top = '0';
body.before(myCanvas);//before插入可以将canvas插入到body前面
body.style.opacity = 0.9;
2、进行浏览器兼容

这里是在做Chrome浏览器的插件,本来是可以忽略这一部分的,但我还是给大家加上,也可以单独提取到html页面展示

window.requestAnimFrame=(function(){
    return window.requestAnimationFrame||
        window.webkitRequestAnimationFrame||
        window.mozRequestAnimationFrame||
        function(callback){
        window.setTimeout(callback,1000/60)
    }
})();
3、创建烟花对象
function Firework(sx,sy,tx,ty){
    this.x=sx;
    this.y=sy;
    this.sx=sx;
    this.sy=sy;
    this.tx=tx;
    this.ty=ty;
    //计算发射点和绽放点的距离
    this.distanceToTarget=calculateDistance(sx,sy,tx,ty);
    //运动距离
    this.distanceTraveled=0;
    //生成的运动轨迹
    this.coordinates=[];
    this.coordinateCount=3;
    while(this.coordinateCount--){
        this.coordinates.push([this.x,this.y])
    }
    this.angle=Math.atan2(ty-sy,tx-sx);
    this.speed=2;
    this.acceleration=1.05;
    this.brightness=random(50,70);//烟花的亮度
    this.targetRadius=1//烟花圈的半径
}
4、更新烟花位置
Firework.prototype.update=function(index){
    this.coordinates.pop();
    this.coordinates.unshift([this.x,this.y]);
    if(this.targetRadius<8){
        this.targetRadius+=0.3
    }else{
        this.targetRadius=1
    }
    this.speed*=this.acceleration;
    var vx=Math.cos(this.angle)*this.speed,
        vy=Math.sin(this.angle)*this.speed;
    this.distanceTraveled=calculateDistance(this.sx,this.sy,this.x+vx,this.y+vy);
    //如果烟花运行距离大于或等于初始位置到目标位置之间的距离,生成新烟花并移除当前烟花,否则更新烟花位置
    if(this.distanceTraveled>=this.distanceToTarget){
        //烟花绽放
        createParticles(this.tx,this.ty);
        //销毁烟花点
        fireworks.splice(index,1)
    }else{
        this.x+=vx;this.y+=vy
    }
};
5、烟花射线发射效果
Firework.prototype.draw=function(){
    // 重新开始新路径,把之前的路径都清空掉
    ctx.beginPath();
    //先保存一个坐标
    ctx.moveTo(this.coordinates[this.coordinates.length-1][0],this.coordinates[this.coordinates.length-1][1]);
    //从moveTo提供的坐标绘制到指定坐标
    ctx.lineTo(this.x,this.y);
    //设置线条样式
    ctx.strokeStyle="hsl("+hue+", 100%, "+this.brightness+"%)";
    //通过此函数将以上绘制的图形绘制到画布上
    ctx.stroke();
    ctx.beginPath();
    //画出鼠标点击时的圆圈
    //arc(圆心的x坐标,圆心的y坐标,圆的半径,起始角(以弧度计,即l圆心的3点钟位置是0度),结束角,规定应该是顺时针还是逆时针画图(可选))
    ctx.arc(this.tx,this.ty,this.targetRadius,0,Math.PI*2);
    //描边绘制
    ctx.stroke()
};
6、烟花粒子绽放方法定义
function Particle(x,y){
    this.x=x;this.y=y;this.coordinates=[];
    this.coordinateCount=5;
    while(this.coordinateCount--){
        this.coordinates.push([this.x,this.y])
    }
    // 往各个角度绽放
    this.angle=random(0,Math.PI*2);
    this.speed=random(1,10);
    this.friction=0.95;
    this.gravity=1;
    this.hue=random(hue-20,hue+20);
    this.brightness=random(50,80);
    this.alpha=1;
    this.decay=random(0.015,0.03);//粒子消失时间(透明度增加速度)
}
7、烟花粒子绽放
// 烟花绽放	
Particle.prototype.draw=function(){
    ctx.beginPath();
    ctx.moveTo(this.coordinates[this.coordinates.length-1][0],this.coordinates[this.coordinates.length-1][1]);
    ctx.lineTo(this.x,this.y);
    //烟花的颜色
    ctx.strokeStyle="hsla("+this.hue+", 100%, "+this.brightness+"%, "+this.alpha+")";
    ctx.stroke()
};
8、完整代码
let body = document.getElementsByTagName('body')[0];
let myCanvas = document.createElement('canvas');
myCanvas.id = 'canvas';
myCanvas.style.position = 'fixed';
myCanvas.style.left = '0';
myCanvas.style.top = '0';
body.before(myCanvas);//before插入可以将canvas插入到body前面
body.style.opacity = 0.9;
// body.appendChild(myCanvas);

//requestAnimFrame 封装,可以兼容所有浏览器
window.requestAnimFrame=(function(){
	return window.requestAnimationFrame||
		window.webkitRequestAnimationFrame||
		window.mozRequestAnimationFrame||
		function(callback){
			window.setTimeout(callback,1000/60)
			}
	})();
	var canvas=document.getElementById("canvas"),
		// Canvas.getContext(contextID)返回一个用于在画布上绘图的环境;
		// 目前合法参数contextID只有"2d",即二维绘图
		ctx=canvas.getContext("2d"),
		// 获取电脑可视区域宽高
		cw=window.innerWidth,ch=window.innerHeight,
		fireworks=[],//存放烟花数组
		particles=[],//存放绽放粒子数组
		hue=180,//设置颜色范围
		limiterTotal=5,//点击绽放速度
		limiterTick=0,//点击计时器
		timerTotal=40,//自动绽放速度
		timerTick=0,//自动计时器
		mousedown=false,
		mx,my;
		// 设置画布宽高
		canvas.width=cw;canvas.height=ch;
		// 随机函数
	function random(min,max){
		return Math.random()*(max-min)+min
		}
		// 计算两点距离
	function calculateDistance(p1x,p1y,p2x,p2y){
		var xDistance=p1x-p2x,yDistance=p1y-p2y;return Math.sqrt(Math.pow(xDistance,2)+Math.pow(yDistance,2))
		}
		// 定义烟花对象
	function Firework(sx,sy,tx,ty){
		this.x=sx;
		this.y=sy;
		this.sx=sx;
		this.sy=sy;
		this.tx=tx;
		this.ty=ty;
		this.distanceToTarget=calculateDistance(sx,sy,tx,ty);
		//运动距离
		this.distanceTraveled=0;
		//生成的运动轨迹
		this.coordinates=[];
		this.coordinateCount=3;
		while(this.coordinateCount--){
			this.coordinates.push([this.x,this.y])
			}
		this.angle=Math.atan2(ty-sy,tx-sx);
		this.speed=2;
		this.acceleration=1.05;
		this.brightness=random(50,70);//烟花的亮度
		this.targetRadius=1//烟花圈的半径
		}
		//更新烟花位置
	Firework.prototype.update=function(index){
		this.coordinates.pop();
		this.coordinates.unshift([this.x,this.y]);
		if(this.targetRadius<8){
			this.targetRadius+=0.3
			}else{
				this.targetRadius=1
				}
		this.speed*=this.acceleration;
		var vx=Math.cos(this.angle)*this.speed,
			vy=Math.sin(this.angle)*this.speed;
		this.distanceTraveled=calculateDistance(this.sx,this.sy,this.x+vx,this.y+vy);
		 //如果烟花运行距离大于或等于初始位置到目标位置之间的距离,生成新烟花并移除当前烟花,否则更新烟花位置
		if(this.distanceTraveled>=this.distanceToTarget){
			//烟花绽放
			createParticles(this.tx,this.ty);
			//销毁烟花点
			fireworks.splice(index,1)
			}else{
				this.x+=vx;this.y+=vy
				}
			};
	// 烟花射线发射
	Firework.prototype.draw=function(){
		// 重新开始新路径,把之前的路径都清空掉
		ctx.beginPath();
		//先保存一个坐标
		ctx.moveTo(this.coordinates[this.coordinates.length-1][0],this.coordinates[this.coordinates.length-1][1]);
		//从moveTo提供的坐标绘制到指定坐标
		ctx.lineTo(this.x,this.y);
		//设置线条样式
		ctx.strokeStyle="hsl("+hue+", 100%, "+this.brightness+"%)";
		//通过此函数将以上绘制的图形绘制到画布上
		ctx.stroke();
		ctx.beginPath();
		//画出鼠标点击时的圆圈
		//arc(圆心的x坐标,圆心的y坐标,圆的半径,起始角(以弧度计,即l圆心的3点钟位置是0度),结束角,规定应该是顺时针还是逆时针画图(可选))
		ctx.arc(this.tx,this.ty,this.targetRadius,0,Math.PI*2);
		//描边绘制
		ctx.stroke()
		};
	//烟花绽放方法
	function Particle(x,y){
		this.x=x;this.y=y;this.coordinates=[];
		this.coordinateCount=5;
		while(this.coordinateCount--){
			this.coordinates.push([this.x,this.y])
			}
		// 往各个角度绽放
		this.angle=random(0,Math.PI*2);
		this.speed=random(1,10);
		this.friction=0.95;
		this.gravity=1;
		this.hue=random(hue-20,hue+20);
		this.brightness=random(50,80);
		this.alpha=1;
		this.decay=random(0.015,0.03);//粒子消失时间(透明度增加速度)
		}
	Particle.prototype.update=function(index){
		this.coordinates.pop();
		this.coordinates.unshift([this.x,this.y]);
		//粒子运动
		this.speed*=this.friction;
		this.x+=Math.cos(this.angle)*this.speed;
		this.y+=Math.sin(this.angle)*this.speed+this.gravity;
		this.alpha-=this.decay;//透明度增加
		if(this.alpha<=this.decay){
			particles.splice(index,1)//销毁烟花绽放粒子
			}
		};
	// 烟花绽放	
	Particle.prototype.draw=function(){
		ctx.beginPath();
		ctx.moveTo(this.coordinates[this.coordinates.length-1][0],this.coordinates[this.coordinates.length-1][1]);
		ctx.lineTo(this.x,this.y);
		//烟花的颜色
		ctx.strokeStyle="hsla("+this.hue+", 100%, "+this.brightness+"%, "+this.alpha+")";
		ctx.stroke()
		};
	// 创建粒子
	function createParticles(x,y){
		//烟花绽放粒子数量
		var particleCount=200;
		while(particleCount--){
			particles.push(new Particle(x,y))
			}
		}
	function loop(){
		 // 让浏览器循环调用指定的函数来更新动画。
		requestAnimFrame(loop);
		hue+=0.5;
		ctx.globalCompositeOperation="destination-out";
		ctx.fillStyle="rgba(0, 0, 0, 0.5)";
		ctx.fillRect(0,0,cw,ch);
		ctx.globalCompositeOperation="lighter";
		var i=fireworks.length;
		while(i--){
			fireworks[i].draw();
			fireworks[i].update(i)
			}
		var i=particles.length;
		while(i--){
			particles[i].draw();
			particles[i].update(i)
			}
		// 随机自动选择位置
		if(timerTick>=timerTotal){
			//鼠标没有点击的情况
			if(!mousedown){
				// fireworks.push(new Firework(cw/2,ch,random(0,cw),random(0,ch/2)));
				timerTick=0
				}
			}else{
				timerTick++
			}
		// 鼠标点击位置
		if(limiterTick>=limiterTotal){
			if(mousedown){
				fireworks.push(new Firework(cw/2,ch,mx,my));
				limiterTick=0
				}
			}else{
				limiterTick++
			}
		}
	body.addEventListener("mousemove",function(e){
		mx=e.pageX-body.offsetLeft - window.scrollX;//鼠标点击坐标 - body偏移量 - 窗口滚动距离
		my=e.pageY-body.offsetTop - window.scrollY;//鼠标点击坐标 - body偏移量 - 窗口滚动距离
		});
	body.addEventListener("mousedown",function(e){
		// e.preventDefault();
		mousedown=true
		});
	body.addEventListener("mouseup",function(e){
		// e.preventDefault();
		mousedown=false
		});
	window.onload=loop;

添加插件到Chrome

(1)下载代码到本地

码云Gitee: [gitee.com/zheng_yongt…]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-50UQFoOZ-1641831055753)(G:\Gitee仓库\md-document-warehouse\博客\image\浏览器点击烟花效果.jpg)]

如上图,圈住的就是本插件的项目目录,将Chrome-fireworkClick这个文件夹拉入到Chrome扩展管理中去就可以了,喜欢的可以顺便点个星星,十分感谢。

更多插件

浏览器网页背景换肤插件 浏览器桌面挂件动画插件 B站视频评论屏蔽插件 将B站视频设置为浏览器背景

源码

码云(gitee):gitee.com/zheng_yongt…

GitHub:github.com/yongtaozhen…

资源下载

csdn资源下载