节,作为全球华人最重要的传统节日,叠加7日连续休假的因素,可以在很多市场领域构成一个独特的相关时间市场。一些产品或服务只有在春节假期存在供给,一些产品或服务则会在春节假期迎来一年里的需求高峰。前者如笔者曾经在《央视春晚推广百度红包违反<反垄断法>吗?》中提到的除夕央视春晚,后者如春节档期电影(相关讨论参见《春节档+情人节+影院限座+……恐催生电影票价串谋 》《回眸(2018):谁是限制春节档电影票补的最大赢家 》)。
如果立足于以往国内的反垄断执法实践,最与春节密切相关的行业当属——烟花爆竹行业:
可见,至少从以往工商系统反垄断执法实践来看,烟花行业典型的限制竞争行为就是划分地域市场的垄断协议。这样的情况恐怕在全国范围并不少见,远不止上述三个公开的案例。上述三个案例中,只有河南固始县烟花爆竹行业垄断协议案没收了违法所得。而不罚没违法所得,违法成本低,这类违法行为反复发生,或者长期延续的可能性就比较高。
另一方面,由于以往工商系统反垄断执法只对非价格类垄断协议拥有管辖权,所以也不排除烟花行业还长期存在纵向或横向的限制价格竞争协议,但原发改委系统反垄断执法机构,或者现国家市场监督管理总局及地方市监局反垄断执法机构还没有发现,或者至少还没有公开结案。
值得注意的是,内蒙古自治区赤峰市烟花行业的垄断协议实际上与相关主管部门涉嫌存在滥用行政权力组织经营者实施限制竞争行为有关。所以,也不排除其他地区也存在类似情况,值得各地市监局关注。
canvas 两种拖尾效果实现烟花:视觉盛宴的代码艺术
**引言**
在Web前端开发领域,HTML5 Canvas以其强大的图形渲染能力,为开发者提供了无限可能。本文将聚焦于如何利用Canvas API创建出绚丽夺目的烟花特效,并重点解析两种不同风格的烟花拖尾效果实现方式。通过详细的代码示例和解析,你将学会如何打造一场属于自己的线上烟火晚会,让观众沉浸在美轮美奂的视觉盛宴之中。
## **一、基础概念与准备工作**
### **1. 创建Canvas元素**
首先,在HTML中设置一个`canvas`元素作为画布:
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Canvas烟花特效</title>
<style>
canvas {
display: block;
margin: auto;
background-color: #000;
}
</style>
</head>
<body>
<canvas id="fireworksCanvas" width="800" height="600"></canvas>
<script src="fireworks.js"></script>
</body>
</html>
```
### **2. 获取Canvas上下文**
在JavaScript文件(如上例中的`fireworks.js`)中获取Canvas上下文:
```javascript
const canvas=document.getElementById('fireworksCanvas');
const ctx=canvas.getContext('2d');
```
## **二、基于点阵的烟花拖尾效果**
### **原理**
本方法采用点阵形式模拟烟花爆炸后的粒子轨迹,每个粒子随着时间推移逐渐消散或淡出。
```javascript
class Particle {
constructor(x, y, speed, color) {
this.x=x;
this.y=y;
this.speed=speed;
this.color=color;
// 其他属性...
}
update() {
// 更新粒子位置
this.y -=this.speed;
// 淡出处理...
}
draw(ctx) {
ctx.fillStyle=this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, 1, 0, Math.PI * 2);
ctx.fill();
}
}
// 烟花类,包含多个粒子对象
class FireworkWithDotsTrail {
// 初始化、更新、绘制方法...
}
```
### **实现过程**
1. 在烟花发射时生成一组随机位置、速度和颜色的粒子。
2. 每帧更新所有粒子的位置和透明度,并绘制到画布上。
3. 当粒子超出屏幕或者透明度达到一定程度时,重新生成新的粒子以维持烟花的持续效果。
## **三、基于线条追踪的烟花拖尾效果**
### **原理**
此方法通过连续记录烟花移动路径上的关键点,并连接这些点形成一条平滑的线条来展现拖尾效果。
```javascript
class FireworkWithLineTrail {
constructor(startX, startY, endX, endY, color) {
this.startX=startX;
this.startY=startY;
this.endX=endX;
this.endY=endY;
this.color=color;
this.trailPoints=[[startX, startY]];
}
update(position) {
this.endX=position.x;
this.endY=position.y;
this.trailPoints.push([this.endX, this.endY]);
// 清理过旧的轨迹点...
}
draw(ctx) {
ctx.beginPath();
ctx.strokeStyle=this.color;
for (let i=0; i < this.trailPoints.length - 1; i++) {
const [x1, y1]=this.trailPoints[i];
const [x2, y2]=this.trailPoints[i + 1];
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
}
ctx.stroke();
}
}
```
### **实现过程**
1. 初始化烟花发射位置和目标方向,创建一个包含起点坐标的轨迹点数组。
2. 每次烟花移动时,添加新的坐标点至轨迹点数组,并清理超出指定数量的旧轨迹点。
3. 绘制时,遍历轨迹点数组并连线,形成拖尾效果。
## **四、完整示例及动画循环**
为了实现动态效果,我们需要使用`requestAnimationFrame`进行动画循环:
```javascript
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
fireworks.forEach((firework)=> firework.updateAndDraw());
requestAnimationFrame(animate);
}
// 初始化若干烟花实例并开始动画循环
const fireworks=[/*...*/];
animate();
```
**结语**
通过以上介绍,我们成功地展示了如何利用Canvas技术在网页上实现两种不同的烟花拖尾效果。无论是点阵式的粒子轨迹,还是线条追踪形成的连贯轨迹,都能带给用户强烈的视觉冲击力。理解并掌握这两种实现方式,无疑会让你在Web前端设计与开发领域更加游刃有余,能够创造出更多惊艳的交互式视觉体验。而实际应用中,根据具体需求,还可以进一步优化细节,例如增加色彩渐变、粒子形状变化等特性,使烟花特效更为丰富多样。不断探索Canvas的无穷魅力,你将在Web世界中描绘出属于自己的璀璨星空!
上就要到2022年了,于是用前端语言(HTML+css+JavaScript)写了一个跨年倒计时代码,祝大家在新的一年里:所念的人平安喜乐,所想的事顺心如意!
代码:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>新年快乐</title><!-- 这是网页标题 -->
<style>
body{
overflow: hidden;
margin: 0;
}
h1{
position: fixed;
top: 30%;
left: 0;
width: 100%;
text-align: center;
transform:translateY(-50%);
font-family: 'Love Ya Like A Sister', cursive;
font-size: 60px;
color: #c70012;
padding: 0 20px;
}
h1 span{
position: fixed;
left: 0;
width: 100%;
text-align: center;
margin-top:30px;
font-size:40px;
}
</style>
</head>
<body>
<h1 id="h1"></h1>
<canvas></canvas> <!--canvas 画布-->
<script>
var canvas=document.querySelector("canvas"),
ctx=canvas.getContext("2d");
var ww,wh;
function onResize(){
ww=canvas.width=window.innerWidth;
wh=canvas.height=window.innerHeight;
}
ctx.strokeStyle="red";
ctx.shadowBlur=25;
ctx.shadowColor="hsla(0, 100%, 60%,0.5)";
var precision=100;
var hearts=[];
var mouseMoved=false;
function onMove(e){
mouseMoved=true;
if(e.type==="touchmove"){
hearts.push(new Heart(e.touches[0].clientX, e.touches[0].clientY));
hearts.push(new Heart(e.touches[0].clientX, e.touches[0].clientY));
}
else{
hearts.push(new Heart(e.clientX, e.clientY));
hearts.push(new Heart(e.clientX, e.clientY));
}
}
var Heart=function(x,y){
this.x=x || Math.random()*ww;
this.y=y || Math.random()*wh;
this.size=Math.random()*2 + 1;
this.shadowBlur=Math.random() * 10;
this.speedX=(Math.random()+0.2-0.6) * 8;
this.speedY=(Math.random()+0.2-0.6) * 8;
this.speedSize=Math.random()*0.05 + 0.01;
this.opacity=1;
this.vertices=[];
for (var i=0; i < precision; i++) {
var step=(i / precision - 0.5) * (Math.PI * 2);
var vector={
x : (15 * Math.pow(Math.sin(step), 3)),
y : -(13 * Math.cos(step) - 5 * Math.cos(2 * step) - 2 * Math.cos(3 * step) - Math.cos(4 * step))
}
this.vertices.push(vector);
}
}
Heart.prototype.draw=function(){
this.size -=this.speedSize;
this.x +=this.speedX;
this.y +=this.speedY;
ctx.save();
ctx.translate(-1000,this.y);
ctx.scale(this.size, this.size);
ctx.beginPath();
for (var i=0; i < precision; i++) {
var vector=this.vertices[i];
ctx.lineTo(vector.x, vector.y);
}
ctx.globalAlpha=this.size;
ctx.shadowBlur=Math.round((3 - this.size) * 10);
ctx.shadowColor="hsla(0, 100%, 60%,0.5)";
ctx.shadowOffsetX=this.x + 1000;
ctx.globalCompositeOperation="screen"
ctx.closePath();
ctx.fill()
ctx.restore();
};
function render(a){
requestAnimationFrame(render);
hearts.push(new Heart())
ctx.clearRect(0,0,ww,wh);
for (var i=0; i < hearts.length; i++) {
hearts[i].draw();
if(hearts[i].size <=0){
hearts.splice(i,1);
i--;
}
}
}
onResize();
window.addEventListener("mousemove", onMove);
window.addEventListener("touchmove", onMove);
window.addEventListener("resize", onResize);
requestAnimationFrame(render);
window.onload=function starttime(){
time(h1,'2022,01,01'); // 2022年元旦时间
ptimer=setTimeout(starttime,1000); // 添加计时器
}
function time(obj,futimg){
var nowtime=new Date().getTime(); // 现在时间转换为时间戳
var futruetime=new Date(futimg).getTime(); // 未来时间转换为时间戳
var msec=futruetime-nowtime; // 毫秒 未来时间-现在时间
var time=(msec/1000); // 毫秒/1000
var day=parseInt(time/86400); // 天 24*60*60*1000
var hour=parseInt(time/3600)-24*day; // 小时 60*60 总小时数-过去的小时数=现在的小时数
var minute=parseInt(time%3600/60); // 分 -(day*24) 以60秒为一整份 取余 剩下秒数 秒数/60 就是分钟数
var second=parseInt(time%60); // 以60秒为一整份 取余 剩下秒数
obj.innerHTML="<br>距离2022年还有:<br>"+day+"天"+hour+"小时"+minute+"分"+second+"秒"+"<br><span>愿我所念的人平安喜乐,<br>愿我所想的事顺心如意。<br>May the people I think of be safe and happy, <br>and may the things I think of be all right.</span>"
return true;
}
</script>
</body>
</html>
倒计时效果:
上面只是一个动图,时间会一直倒计时的。另外大家还可以加烟花效果,就是当到了春节零点的时候会进入另一个页面,有烟花和音效,想想就很不错呀!当然,写这种类型的代码也不止前端可以,大家也可以试试其他编程语言呀!
另外,对于学习编程或者在工作想升职的小伙伴,如果你想更好的提升你的编程能力帮助你提升水平!笔者这里或许可以帮到你~
编程学习书籍分享:
编程学习视频分享:
分享(源码、项目实战视频、项目笔记,基础入门教程)
欢迎转行和学习编程的伙伴,利用更多的资料学习成长比自己琢磨更快哦!
对于C/C++感兴趣可以关注小编在后台私信我:【编程交流】一起来学习哦!可以领取一些C/C++的项目学习视频资料哦!已经设置好了关键词自动回复,自动领取就好了!
*请认真填写需求信息,我们会在24小时内与您取得联系。