節,作為全球華人最重要的傳統節日,疊加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小時內與您取得聯系。