摘要:代碼文件每周一點動畫系列文章目前已經更新了篇,今天給大家發個福利。粒子的位置為,我們作為參數傳入。粒子切換粒子切換的代碼在中,很簡單,就是綁定了兩個事件。
代碼文件
每周一點canvas動畫系列文章目前已經更新了12篇,今天給大家發個福利。我們使用canvas來制作一個小的效果。這個小效果是我從codePen上看到的,我對其做了些修改增強,添加了一些新的功能。UI界面就如下圖中看到的樣子。我們要實現的效果就如我在圖中操作的那樣,在輸入框中輸入文字(不管中文,還是英文,還是各種表情也好)都可以在canvas畫布中通過眾多的粒子組成,在側邊欄中還有很多控件,它們可以控制粒子的各方面屬性,以此來形成各種不同的絢麗效果。
1.目錄結構 2.UI界面UI界面的組成很簡單,主要有側邊欄控制臺和canvas畫布兩部分組成
...
在側邊欄中有一系列的控制條,他們控制著粒子的各種屬性,包括文字輸入框:
控制條
粒子選擇
圓形 方塊
在這我就不一一列舉了!CSS樣式文件主要是對UI界面的布局和樣式處理,具體請查看代碼文件。
3.側邊欄滑動當點擊菜單按鈕時,側邊欄滑出,再次點擊縮回。采用classList來切換滑出和縮回的class,在sidebar.js中
var btn = document.getElementById("btn"); var control = document.getElementById("control"); btn.addEventListener("click", function(e){ control.classList.toggle("slide"); }, false)
這樣我們的基礎界面就搭建完成。下面就到了我們這個動畫的核心思想
4.準備工作首先,我們在我們的index.js文件中定義我們需要的一些變量
var canvas = document.getElementById("canvas"); context = canvas.getContext("2d"); W = canvas.width = window.innerWidth; H = canvas.height = window.innerHeight; gridY = 7, gridX = 7; type = "ball"; var message = document.getElementById("message"), gravity = document.getElementById("gra"), duration = document.getElementById("dur"), speed = document.getElementById("speed"), radius = document.getElementById("rad"), resolution = document.getElementById("res"); graVal = parseFloat(gravity.value); durVal = parseFloat(duration.value); spdVal = parseFloat(speed.value); radVal = parseFloat(radius.value); resVal = parseFloat(resolution.value); colors = [ "#f44336", "#e91e63", "#9c27b0", "#673ab7", "#3f51b5", "#2196f3", "#03a9f4", "#00bcd4", "#009688", "#4CAF50", "#8BC34A", "#CDDC39", "#FFEB3B", "#FFC107", "#FF9800", "#FF5722" ]; function change(){ 。。。 } function changeV() { 。。。 } (function drawFrame(){ window.requestAnimationFrame(drawFrame, canvas); context.clearRect(0, 0, W, H); 。。。 }())
注意這里的的context, W, H等我們定義的是全局變量。
這里有兩個變量可能你不知道他是干什么的gridX和gridY,之后我會詳細介紹。
這個文件是我們整個動畫效果的核心,只有理解了它,你才能了解這個效果的實現原理。因為不是很長,這里我把文件全部列出:
function Shape(x, y, texte){ this.x = x; this.y = y; this.size = 200; this.text = texte; this.placement = []; } Shape.prototype.getValue = function(){ context.textAlign = "center"; context.font = this.size + "px arial"; context.fillText(this.text, this.x, this.y); var idata = context.getImageData(0, 0, W, H); var buffer32 = new Uint32Array(idata.data.buffer); for(var j=0; j < H; j += gridY){ for(var i=0 ; i < W; i += gridX){ if(buffer32[j * W + i]){ var particle = new Particle(i, j, type); this.placement.push(particle); } } } context.clearRect(0, 0, W, H); }
接下來,我就詳細的解一下該文件的代碼!首先我們新建了一個構造函數Shape,該構造函數有3個參數:
x , y: 要繪制的文字的位置
texte: 要繪制的文字
我們設置了文字的大小為200px, 并且定義了一個屬性placement,這個屬性是一個數組。so wired!它是干什么的呢?別急,繼續往下走。
接下來我們在原型對象上定義了一個方法getValue.這幾行代碼:
context.textAlign = "center"; context.font = this.size + "px arial"; context.fillText(this.text, this.x, this.y);
很簡單,設置文字對其方式,字體大小,并且通過fillText()在canvas上繪制文字。如果此時在控制欄中輸入文字,在index.js中新建一個shape對象,并把文字傳入,再調用getValue方法就可以看到你已經把輸入的文字繪制到了canvas中,當然這時候忽略下面的代碼啊!
回到正題,接下來我們調用了context.getImageData(),它是canvas繪制圖片的API接口,通過它我們可以得到需要繪制的圖片的數據內容。也許你會問,它是用來獲取canvas上繪制的圖片的數據內容,可是我們這并沒有繪制圖片啊?
其實,該方法的作用并不只是局限于獲取圖片的內容。只要canvas上有內容,不管是繪制的文字,還是圖形它都能獲取,甚至是空白的canvas它也能獲取,只不過此時的數據都是0。
那么通過該API獲取的內容是什么樣的呢?首先,我們嘗試獲取一張空canvas的內容
var canvas = document.getElementById("canvas"), context = canvas.getContext("2d"); var imgData = context.getImageData(0, 0, canvas.width, canvas.height); console.log(imgData);
結果如下:
我們看到,這里的imgData是一個對象,該對象的第一個屬性就是data,是一個8位無符號整數的類型化數組Uint8ClampedArray。打開data看看都有什么,這里我隨便打開其中的一個看看。
因為canvas為空,所以數據都為零。現在我們換一下,在canvas中畫一個藍色的矩形。
context.fillStyle = "#49f"; context.fillRect(0, 0, canvas.width,canvas.height); var imgData = context.getImageData(0, 0, canvas.width, canvas.height); console.log(imgData);
看看,我們的的數據是不是不為零了!OK! 原理我在這解釋的都差不多了,我們回到正題,看下一行代碼。
var buffer32 = new Uint32Array(idata.data.buffer);
idata.data.buffer ,在這里我們調用Uint8ClampedArray對象的buffer屬性,獲取此數組引用的 ArrayBuffer。然后將它傳入Uint32Array對象(32位無符號整數值的類型化數組)。此時,我們看看上面繪制藍色矩形的數據變成什么樣了,首先數組長度變為[160000],剛好是上面的8位的四分之一
內容變為
相當于我們把一張圖片的分辨率縮小了,以前有640000個數據, 現在只有160000個數據。當然,在本文中數據的內容不是我們所關心的。我們所關心的是在哪有數據。
所以,接下來,就是在有數據的地方,放上我們的粒子
for(var j=0; j < H; j += gridY){ for(var i=0 ; i < W; i += gridX){ if(buffer32[j * W + i]){ var particle = new Particle(i, j, type); this.placement.push(particle); } } } context.clearRect(0, 0, W, H); //清除所畫內容
我們遍歷整個canvas, 通過buffer32[j * W + i]來判斷這個位置的數據是否為空,如果不為空,那么,在這繪制一個粒子。粒子的位置為(i,j)我們作為參數傳入。當然你也可以在數據為空的地方放上粒子,看看會出現什么樣的效果。
這里用到了gridX和gridY,它們的作用是來判斷每個多少個距離取一次數據。學過信號抽樣的同學應該很好理解,如果你間隔大,抽樣得到的數據就小,反之如果你設定的間隔小,那么抽到的數據就多。在我們的效果中,我們繪制的是文字,同樣的道理,間隔小獲取的數據就多,粒子就多,組成的文字就完整。間隔大獲取的就少。那么粒子組成的文字就不那么完整,這兩個變量的值,通過分辨率控件來綁定。思來想去還是上張圖吧!
6.particles.js 文件該文件就是我們的粒子文件,我就不做過多解釋了,不懂得歡迎提問。
7.粒子切換粒子切換的代碼在slide.js中,很簡單,就是綁定了兩個事件。
/粒子切換 var ball = document.getElementById("ball"); var rect = document.getElementById("rect"); function chose(particleName){ particleName.addEventListener("click", function(e){ this.style.backgroundColor = "orange"; (particleName == ball ? rect : ball).style.backgroundColor = "rgba(0, 0, 0, 0)"; type = (type === "ball" ? "rect" : "ball"); change(); }, false) } chose(ball); chose(rect);
Ok!這個效果的關鍵點,基本都已經講完了,有興趣自己看看吧!!!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/79634.html
摘要:很長時間沒有更新文章了,經過幾個月的時間,事情終于忙完了。今天,在這里為大家分享款特效插件,與其說是分享,不如說是為了方便使用,對前面章節的一些效果的封裝。前面的文章在我修改完善后會逐漸上傳。 很長時間沒有更新文章了,經過幾個月的時間,事情終于忙完了。今天,在這里為大家分享3款canvas特效插件,與其說是分享,不如說是為了方便使用,對前面章節的一些效果的封裝。 1. Martrix....
摘要:按下右側的點擊預覽按鈕可以在當前頁面預覽,點擊鏈接可以打開原始頁面。 按下右側的點擊預覽按鈕可以在當前頁面預覽,點擊鏈接可以打開原始頁面。 1. 一個正 20 面體的骰子https://codepen.io/chrisvfrit... 2. 純 css 寫的夜間景色的視差滾動效果https://codepen.io/danbhala/p... 3. 機器人喝油的動畫https://co...
閱讀 2471·2021-11-17 09:33
閱讀 758·2021-11-04 16:13
閱讀 1329·2021-10-14 09:50
閱讀 692·2019-08-30 15:53
閱讀 3657·2019-08-30 14:18
閱讀 3268·2019-08-30 14:14
閱讀 2093·2019-08-30 12:46
閱讀 3178·2019-08-26 14:05