摘要:主要想法鼠標點擊事件觸發(fā)圓點出現(xiàn)在鼠標處圓點大小,顏色,數(shù)量隨機有一個小白圈做為軌跡不斷改變半徑變大變淡消失圓點向外移動,自身變小,消失。
主要想法:
鼠標點擊事件觸發(fā)圓點出現(xiàn)在鼠標處
圓點大小,顏色,數(shù)量隨機
有一個小白圈做為軌跡,不斷改變半徑變大變淡消失
圓點向外移動,自身變小,消失。隨著移動的距離遠,移動速度跟著變
需要處理的是,從鼠標點擊處可以確定圓點的x,y軸,但是動去哪,怎么動是一個問題,
所以先確定圓點的目標坐標,再從圓點的原始坐標(即鼠標點擊處)向目標坐標移動,并且x,y 成比例 去移動才不會在x,y移動距離不相等的情況下 不平衡
隨機生成圓點目標坐標的函數(shù)代碼:
let endpos = (x, y) => { let angle = random(0, 360) * Math.PI / 180, value = random(20, 150), radius = [-1, 1][random(0, 1)] * value; return { x: x + radius * Math.cos(angle), y: y + radius * Math.sin(angle) } }
因為需要大量的隨機數(shù),所以封裝一個生成隨機數(shù)函數(shù)
let random = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
圓點的移動函數(shù),我們需要的移動是從原始坐標向目標坐標由快而慢。
生成比例分成3段。那就是原始坐標到第一段坐標為第一段,第一段坐標到第二段坐標為第二段,第二段坐標到目標坐標為第三段。如果當前坐標是處于第一段內(nèi),則速度越快,以此類推
現(xiàn)在兩種情況,一種是目標坐標大于原始坐標,那么,第一段就為最接近原始坐標的那一段(Math.max(current, ff) == current ? (Math.max(current, mm) == current ? s : m) : f),第二種情況是目標坐標小于原始坐標,那么就反過來,第一段為離原始坐標最遠的那一段。
//根據(jù)不同距離段設置前行的步伐,分為3個階段,離出發(fā)點近的那一段為速度最快,中間為速度一般,最遠為速度最慢 //區(qū)分目標點小于出發(fā)點的情況 //ratio為兩點之間的距離的行走比例,比例數(shù)值越大,行走越慢 moveFun(start, end, current) { let s = random(26, 35), m = random(20, 25), f = random(15, 20), ff = start.x + ~~((end.x - start.x) / 3), mm = ff + ~~((end.x - start.x) / 3), ratio = end.x >= start.x ? (Math.max(current, ff) == current ? (Math.max(current, mm) == current ? s : m) : f) : (Math.max(current, ff) == current ? f : (Math.max(current, mm) == current ? m : s)), mp = { x: end.x - start.x, y: end.y - start.y }; return { x: Math.abs(mp.x / ratio), y: Math.abs(mp.y / ratio) } }
每一個小圓點做為一個個體,自帶移動函數(shù),和移動的目標坐標。每次Animation時,圓點進行重繪更新最新的坐標
小圓點的代碼:
class Circle { constructor(x, y) { this.r = random(9, 13) this.opos = {} this.x = this.opos.x = x this.y = this.opos.y = y this.colors = ["#FF1461", "#18FF92", "#5A87FF", "#FBF38C"] this.color = this.colors[random(0, this.colors.length)]; this.tpos = endpos(x, y) } creatCircle(ctx) { ctx.beginPath() ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI) ctx.closePath() ctx.fillStyle = this.color ctx.fill() } //根據(jù)不同距離段設置前行的步伐,分為3個階段,離出發(fā)點近的那一段為速度最快,中間為速度一般,最遠為速度最慢 //區(qū)分目標點小于出發(fā)點的情況 //ratio為兩點之間的距離的行走比例,比例數(shù)值越大,行走越慢 moveFun(start, end, current) { let s = random(26, 35), m = random(20, 25), f = random(15, 20), ff = start.x + ~~((end.x - start.x) / 3), mm = ff + ~~((end.x - start.x) / 3), ratio = end.x >= start.x ? (Math.max(current, ff) == current ? (Math.max(current, mm) == current ? s : m) : f) : (Math.max(current, ff) == current ? f : (Math.max(current, mm) == current ? m : s)), mp = { x: end.x - start.x, y: end.y - start.y }; return { x: Math.abs(mp.x / ratio), y: Math.abs(mp.y / ratio) } } //根據(jù)計算出來的移動值去移動 //如果目標坐標大于原始坐標則向右移動,最大不能超過目標坐標,反之向左移動最小不能小于目標坐標 move() { var movepos = this.moveFun(this.opos, this.tpos, this.x); this.x = (this.opos.x > this.tpos.x) ? Math.max(this.x - movepos.x, this.tpos.x) : Math.min(this.x + movepos.x, this.tpos.x) this.y = this.opos.y > this.tpos.y ? Math.max(this.y - movepos.y, this.tpos.y) : Math.min(this.y + movepos.y, this.tpos.y) this.r = Math.max(Math.abs((this.r - Math.random() / 1.2).toFixed(2)), 0) } }
大圓則是從鼠標點擊處創(chuàng)建的一個圓,并不斷改變其半徑向外擴展,并且越來越透明,當它已經(jīng)很大并且很透明時意味著我們的動畫要結(jié)束了,所以以這個為標準,停止動畫,并且清空屏幕
大圓代碼:
class BigCircle { constructor(x, y) { this.bR = random(16, 32) this.overR = random(60, 100) this.x = x this.y = y this.op = 1 } creatBigCircle(ctx) { ctx.beginPath() ctx.arc(this.x, this.y, this.bR, 0, 2 * Math.PI) ctx.closePath() ctx.strokeStyle = "rgba(128, 128, 128, " + this.op + ")" ctx.stroke() } changeR() { this.bR = Math.min(this.bR += random(1, 4), this.overR); this.op = Math.max((this.op - Math.random() / 12).toFixed(2), 0) } //檢查是否運行完畢,以大圓為標準清空屏幕 complete() { return this.bR >= this.overR && this.op <= 0; } }
全部代碼:
//canvas鼠標點擊煙花特效 let endpos = (x, y) => { let angle = random(0, 360) * Math.PI / 180, value = random(20, 150), radius = [-1, 1][random(0, 1)] * value; return { x: x + radius * Math.cos(angle), y: y + radius * Math.sin(angle) } } let random = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min; class Circle { constructor(x, y) { this.r = random(9, 13) this.opos = {} this.x = this.opos.x = x this.y = this.opos.y = y this.colors = ["#FF1461", "#18FF92", "#5A87FF", "#FBF38C"] this.color = this.colors[random(0, this.colors.length)]; this.tpos = endpos(x, y) } creatCircle(ctx) { ctx.beginPath() ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI) ctx.closePath() ctx.fillStyle = this.color ctx.fill() } //根據(jù)不同距離段設置前行的步伐,分為3個階段,離出發(fā)點近的那一段為速度最快,中間為速度一般,最遠為速度最慢 //區(qū)分目標點小于出發(fā)點的情況 //ratio為兩點之間的距離的行走比例,比例數(shù)值越大,行走越慢 moveFun(start, end, current) { let s = random(26, 35), m = random(20, 25), f = random(15, 20), ff = start.x + ~~((end.x - start.x) / 3), mm = ff + ~~((end.x - start.x) / 3), ratio = end.x >= start.x ? (Math.max(current, ff) == current ? (Math.max(current, mm) == current ? s : m) : f) : (Math.max(current, ff) == current ? f : (Math.max(current, mm) == current ? m : s)), mp = { x: end.x - start.x, y: end.y - start.y }; return { x: Math.abs(mp.x / ratio), y: Math.abs(mp.y / ratio) } } //根據(jù)計算出來的移動值去移動 //如果目標坐標大于原始坐標則向右移動,最大不能超過目標坐標,反之向左移動最小不能小于目標坐標 move() { var movepos = this.moveFun(this.opos, this.tpos, this.x); this.x = (this.opos.x > this.tpos.x) ? Math.max(this.x - movepos.x, this.tpos.x) : Math.min(this.x + movepos.x, this.tpos.x) this.y = this.opos.y > this.tpos.y ? Math.max(this.y - movepos.y, this.tpos.y) : Math.min(this.y + movepos.y, this.tpos.y) this.r = Math.max(Math.abs((this.r - Math.random() / 1.2).toFixed(2)), 0) } } class BigCircle { constructor(x, y) { this.bR = random(16, 32) this.overR = random(60, 100) this.x = x this.y = y this.op = 1 } creatBigCircle(ctx) { ctx.beginPath() ctx.arc(this.x, this.y, this.bR, 0, 2 * Math.PI) ctx.closePath() ctx.strokeStyle = "rgba(128, 128, 128, " + this.op + ")" ctx.stroke() } changeR() { this.bR = Math.min(this.bR += random(1, 4), this.overR); this.op = Math.max((this.op - Math.random() / 12).toFixed(2), 0) } //檢查是否運行完畢,以大圓為標準清空屏幕 complete() { return this.bR >= this.overR && this.op <= 0; } } window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; window.clearRequestTimeout = window.cancelAnimationFrame || window.mozCancelRequestAnimationFrame || window.webkitCancelRequestAnimationFrame || window.msCancelRequestAnimationFrame; let c = document.getElementById("fireworks"), w = c.width = c.offsetWidth, h = c.height = c.offsetHeight, ctx = c.getContext("2d"), nums = 40, circles = [], bCircle = null, animationId = false; let int = function(x, y) { circles = [] if (animationId) clearRequestTimeout(animationId) for (let i = nums; i-- > 0;) { circles.push(new Circle(x, y)) } bCircle = new BigCircle(x, y) creat() } let creat = function() { ctx.clearRect(0, 0, w, h); circles.forEach(function(v) { v.move(); v.creatCircle(ctx) }) bCircle.changeR() bCircle.creatBigCircle(ctx) animationId = requestAnimationFrame(creat) if (bCircle.complete()) { //以大圓為標準,清空屏幕停止動畫 ctx.clearRect(0, 0, w, h); clearRequestTimeout(animationId) } } c.onclick = function(e) { e = e || window.event; int(e.clientX, e.clientY) }
html為
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/83391.html
摘要:簡易版時鐘時鐘清除畫布,每次執(zhí)行重新繪圖,解決時鐘模糊,邊框有鋸齒。 canvas 簡易版時鐘 showImg(https://segmentfault.com/img/bVDNx7?w=405&h=370); 時鐘 *{ margin:0; padding:0; } bod...
摘要:簡易版時鐘時鐘清除畫布,每次執(zhí)行重新繪圖,解決時鐘模糊,邊框有鋸齒。 canvas 簡易版時鐘 showImg(https://segmentfault.com/img/bVDNx7?w=405&h=370); 時鐘 *{ margin:0; padding:0; } bod...
摘要:主要功能就是拖動標尺變動價格。整個標尺的長度為,步長為元。金額顯示首先,增加一個輸入框,然后獲取它。輸入金額移動標尺標尺的移動除了拖動以外,我們也希望通過金額輸入框來達到。 效果源碼 終于到年底了,再過兩天我也要回家過年了,想想就激動呢!今天給大家?guī)硪粋€基于移動端的canvas價格選擇效果。 showImg(https://segmentfault.com/img/bV3QGd?w...
閱讀 2563·2021-11-22 12:05
閱讀 3450·2021-10-14 09:42
閱讀 1685·2021-07-28 00:15
閱讀 1988·2019-08-30 11:08
閱讀 1486·2019-08-29 17:31
閱讀 929·2019-08-29 16:42
閱讀 2338·2019-08-26 11:55
閱讀 2117·2019-08-26 11:49