ไม่มีสิ่งที่ดีที่สุด มีแต่ดีกว่า ดังที่ชื่อเรื่องระบุไว้ บทความนี้ต้องการแบ่งปันเอฟเฟกต์การเคลื่อนที่ของอนุภาคที่ได้รับจาก Canvas เท่านั้น ให้ความรู้สึกเหมือนพาดหัวข่าวเล็กน้อย แต่จากอีกมุมมองหนึ่ง แทบจะไม่ถือว่าพราวเลย แม้ว่าสีจะไม่เกี่ยวอะไรกับความพราว แต่เอฟเฟกต์การเคลื่อนไหวก็ยังพราวอยู่เล็กน้อย เอาล่ะ มาเริ่มเอฟเฟกต์ที่เรียกว่าพราวกันเถอะ!
ไปที่โค้ดโดยตรง หากคุณไม่เข้าใจ คุณสามารถอ่านความคิดเห็นเกี่ยวกับโค้ดได้ คุณอาจจะเข้าใจแนวคิดทั่วไป
รหัสเอชทีเอ็ม
<!DOCTYPE html><html lang=en><head><meta charset=UTF-8><title>Canvas ให้เอฟเฟกต์การเคลื่อนไหวของอนุภาคที่น่าทึ่ง - ส่วนหน้าของไลบรารีระบบคลาวด์</title><style>* { ระยะขอบ: 0; : 0;}html,body { width: 100%; height: 100%;} canvas { display: block; background: #000;}body::-webkit-scrollbar{ จอแสดงผล: none;}.operator-box{ ตำแหน่ง: คงที่; ด้านบน: 0; ซ้าย: 50%; เส้นขอบ: 1px solid #fff; พื้นหลัง: rgba(255,255,255,0.5); (-50%); แปลง: แปล X (-50%);} .back-type, .back-animate { ขอบขวา: 20px;}.flex-box{ จอแสดงผล: flex; justify-content: center; align-items: center;}#input-text{ line-height: 35px; 0, 0,0.7); สี: #fff; ขนาดตัวอักษร: 16px; 12px; box-shadow: ใส่ 0 0 12px 1px rgba(0,0,0,0.7);}#input-text::placeholder { color: #ccc; line-height: 55px;}select{ - ลักษณะที่ปรากฏของ webkit: ไม่มี; -moz-ลักษณะที่ปรากฏ: ไม่มี; ลักษณะที่ปรากฏ: ไม่มี; การขยาย: 0px 20px 0px 6px; ความสูง: 35px; สี: #fff; การจัดตำแหน่งข้อความ: ซ้าย; url (ข้อมูล: รูปภาพ / PNG; base64, iVBORw0KGgoAAAANSUhEUgAAAAUAAAAICAYAAAAx8TU7AAAAOUlEQ … R4gPgWEIMAiOYBCS4C8ZDAIrBq4gigNkztQEFMi6AuQHESAPMeXiEMiWfpAAAAAelFTkSuQmCC) ไม่ทำซ้ำ 190px 12px; ขนาดพื้นหลัง: 5px 8px; กล่องเงา: สิ่งที่ใส่เข้าไป 0 0 12px 1px 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=easeOut>dynamics.easeOut</option> option> <option value=linear>dynamics.linear</option> </select> </div> <div class=input-box><ประเภทอินพุต=ข้อความ 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 ตัวเอกของบทความนี้กันก่อน อย่างไรก็ตาม ก่อนที่จะดูโค้ด เราอาจฟังแนวคิดในการบรรลุผลนี้ด้วย:
มีการใช้ผืนผ้าใบ Canvas สามผืนในโค้ด JavaScript, this.iCanvas (โฮมเพจ), this.iCanvasCalculate (ใช้ในการคำนวณความกว้างของข้อความ), this.iCanvasPixel (ใช้ในการวาดข้อความและรับพิกัดตำแหน่งของพิกเซลที่สอดคล้องกับข้อความ ) .
this.iCanvasCalculate และ this.iCanvasPixel ไม่จำเป็นต้องแสดงบนเพจ เป็นเพียงฟังก์ชันเสริมเท่านั้น
นี่คือโค้ดการใช้งาน JS ที่ยอดเยี่ยม
function Circle() { var This = this; this.init(); this.generalRandomParam(); this.ballAnimate(); // หลังจากหน้าต่างเปลี่ยนขนาด, การคำนวณและ รับหน้าจอ window.onresize = function(){ This.stateW = document.body.offsetWidth; This.stateH = document.body.offsetHeight; This.iCanvasW = This.iCanvas.width = This.stateW; This.iCanvasH = This.iCanvas.height = This.stateH; This.ctx = This.iCanvas.getContext(2d); }}//เริ่มต้น Circle.prototype.init = function( ){ // ความกว้างและความสูงขององค์ประกอบหลัก 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; // รับสภาพแวดล้อมการวาดภาพ 2 มิติ this.ctx = this.iCanvas.getContext (2d); // แทรกลงในองค์ประกอบเนื้อหา document.body.appendChild (this.iCanvas); this.iCanvasCalculate = document.createElement(canvas); // Canvas ใช้เพื่อบันทึกความกว้างของข้อความที่คำนวณ this.mCtx = this.iCanvasCalculate.getContext(2d); this.mCtx.font = 128px Microsoft Yahei = this.iCanvasPixel = document .createElement (ผ้าใบ); this.iCanvasPixel.setAttribute(style,position:absolute;top:0;left:0;); this.pCtx = null; // Canvas ใช้ในการวาดข้อความ // จำนวนวงกลมที่สร้างขึ้นแบบสุ่ม this.ballNumber = ramdomNumber(1,000 , 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. which === 13){ // ถ้าเป็นคีย์ enter ipu.value = ipu.value.trim(); // ลบช่องว่างนำหน้าและต่อท้าย var pat = /[/u4e00-/u9fa5]/; // การตัดสินของจีน var is Chinese = pat.test(ipu.value); if(ipu.value.length !=0 && is Chinese){ This.inputText = ipu.value; }else{ alert(กรุณากรอกตัวอักษรจีน); ) { กลับ } This.getAnimateType(); This.getTextPixel(); This.isPlay = true; คำนวณความกว้างของข้อความ Circle.prototype.calculateTextWidth = function () { this.textWidth = this.mCtx.measureText(this.inputText).width;}// รับพิกเซลข้อความ Circle.prototype.getTextPixel = function () { ถ้า ( this.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 = ด้านล่าง; this.pCtx.fillText(this.inputText,0,110); 0,0,this.textWidth,this.textHeight).ข้อมูล; this.getTextPixelPosition(this.textWidth,this.textHeight);}//รับตำแหน่งพิกเซลของอนุภาคข้อความ Circle.prototype.getTextPixelPosition = function (width,height) { var left = (this.iCanvasW - width)/2; = (this.iCanvasH - ความสูง)/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; this.imageData[ดัชนี] == 255){ if(this.actionCount<this.ballNumber){ this.balls[this.actionCount].status = 1; this.balls[this.actionCount].targetX = ซ้าย+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, ระยะเวลา: 1024, }); } setTimeout(function(){ This.ballbackType(); },3000);}//อนุภาคกลับสู่ วงกลมไปตามเส้นทางเดิม .prototype.ballBackPosition = function(){ for(var i=0;i<This.actorNumber;i++){ var ball = This.ballActor[i]; dynamics.animate(บอล, { x: ball.backX, y: ball.backY },{ ประเภท: dynamics[this.backDynamics], ระยะเวลา: 991, สมบูรณ์: this.changeStatus (บอล) } }}// รับประเภท|เอฟเฟกต์ภาพเคลื่อนไหว 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(){ ถ้า(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(){ สำหรับ (var i=0;i<this.ballNumber;i++){ var ball = {}; ball.size = 1; สุ่มสร้างรัศมีวงกลม // สุ่มสร้างจุดศูนย์กลางวงกลม 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); this.balls.push(บอล); ball.status = 0; ball.targetX = 0; ball.backX = 0; ball.backY = 0; }}// เปลี่ยนตำแหน่งของวงกลม สำหรับ ( 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; } อื่น ๆ { ball.x = ball.size; } ball.speedX = - ball.speedX; (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.mozRequestAnimationFrame || window.msRequestAnimationFrame; (ฟังก์ชั่น 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]); } })();}//สร้างฟังก์ชันตัวเลขสุ่ม ramdomNumber(min, max) { return Math.random() * (max - min) + min;}
หลังจากอ่านโค้ดแล้ว ฉันเดาว่ามันเป็นเพียงการแสดงเล็กน้อย และมันไม่ได้ทำให้คุณมีความปรารถนาที่จะทำสิ่งนี้ สำหรับสิ่งนี้ ฉันรู้ว่าคุณต้องมั่นใจด้วยตาและปากของคุณ การสาธิตออนไลน์: ตัวอย่างอนุภาคแบบไดนามิก
ไม่มีใครสมบูรณ์แบบ และโค้ดก็เช่นกัน โค้ดที่ดูเหมือนว่าจะทำงานได้อย่างราบรื่นมีข้อบกพร่องไม่มากก็น้อย ปัจจุบันเอฟเฟกต์นี้รองรับเฉพาะภาษาจีนเท่านั้น ในส่วนของภาษาอังกฤษ ฉันต้องทำงานหนักขึ้น ไม่ว่ายังไงก็ตาม ภาษาอังกฤษจะเข้าร่วมทีหลังอย่างแน่นอน มันเป็นแค่เรื่องของเวลา นอกจากนี้ยังมีแอตทริบิวต์ในโค้ดที่ใช้เพื่อทำเครื่องหมายว่าข้อความที่สร้างขึ้นสามารถดำเนินการอีกครั้งได้หรือไม่: this.isPlay ซึ่งยังคงมีข้อบกพร่องเล็กน้อย การเปลี่ยนแปลงสถานะของ this.isPlay จะไม่เปลี่ยนแปลงอย่างแน่นอนในขณะที่อนุภาคกลับมา แต่เปลี่ยนสถานะล่วงหน้า แต่สถานะนี้จะไม่ส่งผลกระทบต่อการดำเนินการตามผลของตัวอย่างนี้โดยสมบูรณ์
ในตัวอย่างนี้ มีการใช้ไลบรารี Dynamics.js โดยส่วนใหญ่จะใช้ฟังก์ชันการเคลื่อนไหวบางอย่างในนั้นเพื่อทำให้อนุภาคเคลื่อนที่ได้น่าประทับใจยิ่งขึ้น แค่นั้นเอง
ข้างต้นคือเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการศึกษาของทุกคน ฉันหวังว่าทุกคนจะสนับสนุน VeVb Wulin Network