ليس هناك الأفضل، بل الأفضل كما يشير العنوان، هذه المقالة تريد فقط مشاركة تأثير حركة الجسيمات الذي تم تحقيقه باستخدام Canvas. يبدو الأمر وكأنه عنوان رئيسي، ولكن من منظور آخر، بالكاد يمكن اعتباره مبهرًا. على الرغم من أن اللون لا علاقة له بالإبهار، إلا أن تأثير الحركة لا يزال مبهرًا بعض الشيء. على أية حال، لنبدأ بهذا التأثير المبهر!
انتقل مباشرة إلى الكود إذا لم تفهمه، يمكنك قراءة تعليقات الكود. ربما ستفهم الفكرة العامة.
كود أتش تي أم أل
<!DOCTYPE html><html lang=en><head><meta charset=UTF-8><title>يحقق القماش تأثيرات مبهرة لحركة الجسيمات - الواجهة الأمامية للمكتبة السحابية</title><style>* { هامش: 0; : 0;}html,body { width: 100% height: 100%;}canvas { العرض: الخلفية: #000;}body::-webkit-scrollbar{ العرض: لا شيء؛}.operator-box{ الموضع: ثابت؛ اليسار: 50%؛ الحدود: 1 بكسل صلب #fff؛ الخلفية: rgba(255,255,0.5); (-50%); تحويل: ترجمة X(-50%);}.back-type,.back-animate{ هامش-يمين: 20px;}.flex-box{ العرض: flex; align-items: center;}#input-text{ line-height: 35px width: 260px height: 35px; 0,0,0.7); اللون: #fff; حجم الخط: 16 بكسل; 12px؛ مربع الظل: داخلي 0 0 12px 1px rgba(0,0,0,0.7);}#input-text::placeholder{ color: #ccc; height: 55px;}select{ - مظهر webkit: لا شيء؛ - مظهر moz: لا شيء؛ الحدود: لا شيء؛ 0 بكسل 6 بكسل؛ الارتفاع: 35 بكسل؛ اللون: #fff؛ محاذاة النص: اليسار؛ url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAAUAAAAICAYAAAAx8TU7AAAAOUlEQ…R4gPgWEIMAiOYBCS4C8ZDAIrBq4gigNkztQEFMi6AuQHESAPMeXiEMiWfpAAAAAAElFTkSuQmCC) بدون تكرار 190 بكسل 12 بكسل حجم الخلفية: 5 بكسل 8 بكسل; ظل الصندوق: داخلي 0 0 12 بكسل 1 بكسل rgba(0,0,0,0.7);</style></head><body><div class=operator-box>< div class=flex-box> <div class=back-type>نوع الانتشار: <select name= id=selectType> <option value=back>Return</option> <option value=auto>عشوائي</option> </select> </div> <div class=back-animate>تأثير التشتت (فعال للتوجيه): <select class=back-dynamics id=selectDynamics> <option value= Spring>dynamics.spring</option> <option value=bounce>dynamics.bounce</option> <option value=forceWithGravity>dynamics.forceWithGravity</option> <option value=gravity>dynamics.gravity</option> <option value=easeInOut>dynamics.easeInOut</option> <option value=easeIn>dynamics.easeIn</option> <option value=easeInOut>dynamics.easeOut</ خيار> <option value=linear>dynamics.linear</option> </select> </div> <div class=input-box><input type=text placeholder=أدخل الأحرف الصينية واضغط على Enter id=input-text></div></div></div><script src=dynamics.min.js></script><script src=index.js></ script ><script>var iCircle = new Circle();</script></body></html>
لا يوجد الكثير من كود HTML، فقط عدد قليل من عناصر التشغيل. من السهل أن نفهم في لمحة هنا. لا حاجة لإضاعة الكثير من الكلمات. دعونا نلقي نظرة على كود JavaScript الخاص بالبطل في هذه المقالة، ومع ذلك، قبل النظر إلى الكود، قد نستمع أيضًا إلى فكرة تحقيق هذا التأثير:
يتم استخدام ثلاث لوحات قماشية في كود JavaScript، this.iCanvas (الصفحة الرئيسية)، this.iCanvasCalculate (يستخدم لحساب عرض النص)، this.iCanvasPixel (يستخدم لرسم النص والحصول على إحداثيات موضع وحدات البكسل المقابلة للنص) ) .
لا يلزم عرض this.iCanvasCalculate وthis.iCanvasPixel على الصفحة، فهي مجرد وظائف مساعدة.
إليك رمز تنفيذ JS الرائع
function Circle() { var This = this.init(); this.generalRandomParam(); this.drawCircles(); this.getUserText(); احصل على الشاشة window.onresize = function(){ This.stateW = document.body.offsetWidth; This.stateH = document.body.offsetHeight; This.iCanvas.width = This.stateW; This.iCanvasH = This.iCanvas.height = This.stateH; This.ctx = This.iCanvas.getContext(2d); ){ // عرض العنصر الأصلي وارتفاعه this.stateW = document.body.offsetWidth; this.stateH = document.body.offsetHeight; document.createElement(canvas); // قم بتعيين Canvas ليكون له نفس العرض والارتفاع للعنصر الأصلي this.iCanvasW = this.iCanvas.width = this.stateW; this.iCanvasH = this.iCanvas.height = this.stateH; // احصل على بيئة اللوحة ثنائية الأبعاد this.ctx = this.iCanvas.getContext(2d); // أدخل في عنصر الجسم document.body.appendChild(this.iCanvas); this.iCanvasCalculate = document.createElement(canvas); // القماش المستخدم لحفظ عرض النص المحسوب this.mCtx = this.iCanvasCalculate.getContext(2d); this.mCtx.font = 128px Microsoft Yahei; (قماش)؛ this.iCanvasPixel.setAttribute(style,position:absolute;top:0;left:0;); this.pCtx = null // القماش المستخدم لرسم النص // عدد الدوائر التي تم إنشاؤها عشوائيًا this.ballNumber = ramdomNumber(1000); , 2000); // احفظ مصفوفة من جميع الكرات this.balls = []; // احفظ الكرة الأخيرة التي توقفت عن الحركة في الرسوم المتحركة this.animte = null; this.imageData = null; this.textWidth = 0; // احفظ عرض النص الذي تم إنشاؤه this.textHeight = 150; // احفظ ارتفاع النص الذي تم إنشاؤه this.inputText = ; this.actionCount = 0; this.ballActor = []; // احفظ الجزيئات التي تولد النص this.actorNumber = 0; // احفظ عدد الجزيئات التي تولد النص this.backType = back; // تأثير الرسوم المتحركة this.isPlay = false; // الشعار (لا يمكن إنشاؤه أثناء إنشاء النص)}// عرض جميع الدوائر Circle.prototype.drawCircles = function () { for(var i=0;i <this.ballNumber ; ;i++){ this.renderBall(this.balls[0]) }}// احصل على نص إدخال المستخدم Circle.prototype.getUserText = function(){ This = this; // احفظ هذا للإشارة إلى ipu = document.getElementById(input-text); ipu.addEventListener(keydown,function(event){ if(event.what === 13){ // إذا كان هو مفتاح الإدخال ipu.value = ipu.value.trim(); // إزالة المسافات البادئة والزائدة var pat = /[/u4e00-/u9fa5]/ // الحكم الصيني var isChinese = pat.test(ipu.value); if(ipu.value.length !=0 && isChinese){ This.inputText = ipu.value; ) { return } This.getAnimateType(); This.getTextPixel(); احسب عرض النص Circle.prototype.calculateTextWidth = function () { this.textWidth = this.mCtx.measureText(this.inputText).width;}// احصل على بكسلات النص Circle.prototype.getTextPixel = function () { إذا (هذا.pCtx) { this.pCtx.clearRect(0,0,this.textWidth,this.textHeight); } this.calculateTextWidth(this.inputText); this.iCanvasPixel.width = this.textWidth; .pCtx = this.iCanvasPixel.getContext(2d); this.pCtx.font = 128px Microsoft Yahei; this.pCtx.fillStyle = #FF0000; this.pCtx.textBaseline = botom; this.pCtx.fillText(this.inputText,0,110); 0,0,this.textWidth,this.textHeight).data; this.getTextPixelPosition(this.textWidth,this.textHeight);}// احصل على موضع بكسل جسيم النص Circle.prototype.getTextPixelPosition = function (width,height) { var left = (this.iCanvasW - width)/2; = (this.iCanvasH - height)/2; var space = 4; this.actionCount = 0; i=0;i<this.textHeight;i+=space){ for(var j=0;j<this.textWidth;j+=space){ var Index = j*space+i*this.textWidth*4 if( this.imageData[index] == 255){ if(this.actionCount<this.ballNumber){ this.balls[this.actionCount].status = 1; this.balls[this.actionCount].targetX = left+j; this.balls[this.actionCount].targetY = top+i; this.balls[this.actionCount].backX = this.balls[this.actionCount]. x; this.balls[this.actionCount].backY = this.balls[this.actionCount].y; this.ballActor.push(this.balls[this.actionCount]); } } } this.actorNumber = this.ballActor.length; } this.animateToText();}// يتحرك الجسيم إلى الموضع المحدد Circle.prototype.animateToText = function(){ for(var i=0;i<This .actorNumber ;i++){dynamics.animate(This.ballActor[i], { x: this.ballActor[i].targetX, y: this.ballActor[i].targetY },{ type:dynamics.easeIn, Duration: 1024, }); } setTimeout(function(){ This.ballbackType(); },3000);}// تعود الجسيمات إلى ضع دائرة على طول المسار الأصلي .prototype.ballBackPosition = function(){ for(var i=0;i<This.actorNumber;i++){ var ball = This.ballActor[i];dynamics.animate(ball, { x: ball.backX, y: ball.backY },{ النوع:dynamics[this.backDynamics], المدة: 991, Complete:this.changeStatus(ball) } }}// احصل على النوع|تأثير الرسوم المتحركة Circle.prototype.getAnimateType = function() { var SelectType = document.getElementById(selectType); var SelectDynamics = document.getElementById(selectDynamics); this.backType = SelectType.options[selectType.options.selectedIndex].value; this.backDynamics = SelectDynamics.options[selectDynamics.options.selectedIndex].value;}// إعادة تعيين دائرة الانتشار .prototype.ballbackType = function(){ if(this.backType == back){ this.ballBackPosition(); }else{ this.ballAutoPosition(); } this.ballActor = [];}// مبعثر بشكل عشوائي Circle.prototype.ballAutoPosition = function(ball){ for(var i= 0 ;i<this.actorNumber;i++){ this.changeStatus(this.ballActor[i]) }}// تغيير حالة الكرة Circle.prototype.changeStatus = function(ball){ ball.status = 0; if(this.isPlay == true){ this.isPlay = false }}// قم بإنشاء المعلمات ذات الصلة لكل دائرة بشكل عشوائي .prototype.generalRandomParam = function(){ for(var i=0;i<this.ballNumber;i++){ var ball = {}; إنشاء نصف قطر الدائرة بشكل عشوائي // إنشاء مركز الدائرة بشكل عشوائي x الإحداثيات ball.x = ramdomNumber(0+ball.size, this.iCanvasW-ball.size); ball.y = ramdomNumber(0+ball.size, this.iCanvasH-ball ball.speedX = ramdomNumber(-1, 1); ball.speedY = ramdomNumber(-1, 1); ball.status = 0; ball.targetY = 0; ball.backX = 0; for( var i=0;i<this.ballNumber;i++){ if( this.balls[i].status == 0){ this.balls[i].x += this.balls[i].speedX; this.balls[i].y += this.balls[i].speedY; } }}// ارسم دائرة Circle.prototype.renderBall = function(ball){ this.ctx fillStyle = #fff; this.ctx.beginPath(); // يجب إضافته باستخدام this.ctx.arc(ball.x, ball.y, ball.size, 0, 2 * Math.PI); this.ctx. ClosePath(); // يجب إضافة هذا باستخدام this.ctx.fill();}// حكم تصادم الكرة Circle.prototype.collision = function(ball){ for(var i= 0;i<this.ballNumber;i++){ if(ball.x>this.iCanvasW-ball.size || ball.x<ball.size){ if(ball.x>this.iCanvasW-ball.size){ ball.x = this.iCanvasW-ball.size }else{ ball.x = ball.size } ball.speedX = - ball.speedX } if (ball.y>this.iCanvasH-ball.size || ball.y<ball.size){ if(ball.y>this.iCanvasH-ball.size){ ball.y = this.iCanvasH-ball.size; }else{ ball.y = ball.size; } ball.speedY = - ball.speedY; } }}// بدء الرسوم المتحركة Circle.prototype.ballAnimate = function(){ var This = this var animateFrame = window.requestAnimationFrame || window.msRequestAnimationFrame; (function move(){ animte = animateFrame(move); This.ctx.clearRect(0, 0, This.iCanvasW, This.iCanvasH); This.changeposition(); for(var i=0;i <This.ballNumber;i++){ This.collision(This.balls[i]); This.renderBall(This.balls[i] }); })();}// إنشاء رقم عشوائي function ramdomNumber(min, max) { return Math.random() * (max - min) + min;}
بعد قراءة الكود، أعتقد أنه كان مجرد استعراض، ولم يمنحك الرغبة في صنع هذا الشيء، ولهذا السبب، أعلم أنه يجب عليك أن تقتنع بعينيك وفمك. العرض التوضيحي عبر الإنترنت: مثال على الجسيمات الديناميكية.
لا يوجد أحد مثالي، ولا الكود أيضًا. الكود الذي يبدو أنه يعمل بسلاسة به عيوب أكثر أو أقل. حاليًا، هذا التأثير يدعم اللغة الصينية فقط. أما بالنسبة للغة الإنجليزية، فلا بد لي من العمل بجدية أكبر، بغض النظر عن ذلك، ستنضم اللغة الإنجليزية لاحقًا، إنها مجرد مسألة وقت. هناك أيضًا سمة في الكود تُستخدم لتحديد ما إذا كان النص الذي تم إنشاؤه يمكن تنفيذه مرة أخرى: this.isPlay، والذي لا يزال عيبًا صغيرًا. لا يتغير تغيير حالة this.isPlay تمامًا في اللحظة التي تعود فيها الجسيمات. لكنه يغير الحالة مقدما. لكن هذه الحالة لن تؤثر على التنفيذ الكامل لتأثير هذا المثال.
في هذا المثال، تم استخدام مكتبة Dynamics.js بشكل أساسي لاستخدام بعض وظائف الحركة فيها لجعل الجزيئات تتحرك بشكل أكثر إثارة للإعجاب، هذا كل شيء.
ما ورد أعلاه هو المحتوى الكامل لهذه المقالة وآمل أن يكون مفيدًا لدراسة الجميع وآمل أيضًا أن يدعم الجميع شبكة VeVb Wulin.