ตอนที่ฉันดู CSSDesignAwards ฉันพบเอฟเฟกต์ที่แยกเนื้อหารูปภาพ (เว็บไซต์: https://weareludwig.com) คุณสามารถคลิกเพื่อดูมันได้ รู้สึกดีมาก ดังนั้นฉันจึงพยายามนำไปใช้ด้วยตัวเอง และผลที่ได้ก็ค่อนข้างดี ตรวจสอบเอฟเฟกต์ https://codepen.io/geeknoble/pen/OQaOVG
วิเคราะห์อันดับแรก เราจะพบว่าเนื้อหาของรูปภาพแบ่งออกเป็นสี่เหลี่ยมเล็กๆ และแต่ละสี่เหลี่ยมจะถูกแปลแบบสุ่ม ฟังก์ชัน DrawImage ของ Canvas สามารถครอบตัดเนื้อหารูปภาพและวาดลงใน Canvas Canvas ได้ ดังนั้นหลักการใช้งานหลักของเอฟเฟกต์นี้คือการใช้ DrawImage เอฟเฟ็กต์หลักมี 2 ประการ ประการหนึ่งคือการรบกวนและกู้คืนเนื้อหารูปภาพ และอีกประการหนึ่งคือการสลับไปยังรูปภาพถัดไป DrawImage สามารถใช้กับทั้งสองเอฟเฟ็กต์ได้ แต่ระยะการเคลื่อนที่จะแตกต่างกัน เมื่อคุณมีแนวคิดทั่วไปแล้ว คุณก็สามารถเริ่มนำไปปฏิบัติได้
งานเริ่มแรกขั้นแรก เราต้องเริ่มต้นตัวแปรบางอย่าง เช่น ความกว้างและความสูงของรูปภาพ จำนวนสี่เหลี่ยม ขนาดการตัด เป็นต้น จากนั้นคำนวณพิกัดของแต่ละสี่เหลี่ยม และใช้การวนซ้ำสองครั้งเพื่อบันทึกพิกัดสี่เหลี่ยมในข้อมูล . แต่ละสี่เหลี่ยมมีการกระจัดแบบสุ่ม ในหมู่พวกเขา x และ y เป็นตัวแทนของพิกัดของผืนผ้าใบ และ x1 และ y1 เป็นตัวแทนของพิกัดของการครอบตัดรูปภาพ
init: ฟังก์ชั่น (บริบท, ความกว้าง, ความสูง, พื้นที่, img) { this.context = context; this.img = img; this.imgWidth = img[0].width; 0 ].height; this.index = 0; // หมายเลขรูปภาพปัจจุบัน this.width = width; // ความกว้างและความสูงของผ้าใบ this.height = ความสูง; //ความยาวของสี่เหลี่ยมเล็ก this.countX = width / this.area; //จำนวนสี่เหลี่ยมเล็ก ๆ ในทิศทางแนวนอนและแนวตั้ง this.countY = height / this.area; this.wx = this.imgWidth / this .countX; // ความกว้างและความสูงของรูปภาพในสี่เหลี่ยมเล็ก this.wy = this.imgHeight / this.state = true; // สถานะรูปภาพ จริง หมายถึงไม่แยก this.dataFlag = true; สถานะพิกัด จริง หมายถึง ไม่มีการเพิ่มค่าสุ่มนี้ ระยะเวลา = 1,000; // เวลาภาพเคลื่อนไหว this.duration2 = 1500; this.startTime = 0; this.data = []; // ข้อมูลพิกัดสี่เหลี่ยมเล็ก ๆ this.randoms = []; x1 = 0, y1 = 0, x = 0, y = 0; สำหรับ (var i = 0; i < this.countY; i++) { สำหรับ (var j = 0; j < this.countX; j++) { context.drawImage (this.img [this.index], x1, y1, this.wx, this.wy, x, y, this.area, this.area); // พิกัดสี่เหลี่ยมที่เก็บข้อมูล this.data.push({ x1: x1, y1: y1, x: x, y: y }); //เพิ่มค่าสุ่ม this.randoms.push(random(-this.area, this.area)); x1 += this.wx; x += this.area; wy; x = 0; y += this.area; } this.checkMargin();ตรวจจับขอบ
ก่อนที่จะเพิ่มการกระจัดให้กับสี่เหลี่ยม เราต้องพิจารณาว่าพิกัดการแทนที่นั้นเกินขีดจำกัดของรูปภาพหรือไม่ ตัวอย่างเช่น หากสี่เหลี่ยมที่ด้านบนเคลื่อนที่บนแกน y จะสามารถเลื่อนขึ้นไปได้เท่านั้น เงื่อนไขการตัดสินคือว่า พิกัดปัจจุบันบวกค่าการกระจัดน้อยกว่า 0 หรือใหญ่กว่าความกว้างและความสูงของรูปภาพ หากพิกัดที่อัปเดตน้อยกว่า 0 ค่าสุ่มจะต้องเป็นจำนวนลบ คุณต้องเปลี่ยนค่าสุ่มเป็นจำนวนบวก หากค่านั้นมากกว่าความสูงของรูปภาพ ให้เปลี่ยนเป็นจำนวนลบ เนื่องจากแต่ละสี่เหลี่ยมเคลื่อนที่ไปในทิศทางเดียว ฉันจึงเขียนตรงนี้ว่าบิตที่เป็นเลขคู่จะเคลื่อนที่แกน x และบิตที่เป็นเลขคี่จะเคลื่อนที่แกน y
// ตรวจหาขอบ checkMargin: function () { var self = this; this.data.forEach(function (item, index) { if (index % 2 == 0) { // ย้ายแกน x เมื่อดัชนีเป็น ผลคูณของ 2 หรือย้ายแกน y if (item.x1 + self.randoms[index] < 0) // เปลี่ยนเป็นจำนวนบวก self.randoms[index] = -self.randoms[index]; .x1 + self.wx + self.randoms[index] > self.imgWidth ) // เปลี่ยนเป็นจำนวนลบ self.randoms[index] = -Math.abs(self.randoms[index]) } else { if (item.y1 + self .randoms[ดัชนี] < 0) self.randoms[index] = -self.randoms[index]; if (item.y1 + self.randoms[index] + self.wy > self.imgHeight) self.randoms [ดัชนี] = -Math.abs (self.randoms [ดัชนี]) } }) }การแยกและการกู้คืน
การแยกและการคืนค่าเนื้อหาแอนิเมชั่นคือการอัปเดตค่าของพิกัดสี่เหลี่ยม หากต้องการรบกวนเนื้อหา เพียงเพิ่มค่าสุ่มให้กับพิกัดในข้อมูล และการกู้คืนคือการลบค่าสุ่ม
// ตรวจหาขอบ checkMargin: function () { var self = this; this.data.forEach(function (item, index) { if (index % 2 == 0) { // ย้ายแกน x เมื่อดัชนีเป็น ผลคูณของ 2 หรือย้ายแกน y if (item.x1 + self.randoms[index] < 0) // เปลี่ยนเป็นจำนวนบวก self.randoms[index] = -self.randoms[index]; .x1 + self.wx + self.randoms[index] > self.imgWidth ) // เปลี่ยนเป็นจำนวนลบ self.randoms[index] = -Math.abs(self.randoms[index]) } else { if (item.y1 + self .randoms[ดัชนี] < 0) self.randoms[index] = -self.randoms[index]; if (item.y1 + self.randoms[index] + self.wy > self.imgHeight) self.randoms [ดัชนี] = -Math.abs (self.randoms [ดัชนี]) } }) }
หลังจากจัดเก็บพิกัดแล้ว คุณสามารถใช้แอนิเมชั่นการแปลได้ กระบวนการเคลื่อนไหวจะราบรื่น เราสามารถใช้อัลกอริธึมการค่อยๆ เปลี่ยนของ Tween.js ได้ เวลาแอนิเมชั่น สำหรับรายละเอียด โปรดดูบทความของ Zhang Xinxu https://www.zhangxinxu.com/wordpress/2016/12/how-use-tween-js-animation-easing/ Tween.js สามารถใช้เพื่อคำนวณระยะทางที่จะเคลื่อนที่ในแต่ละเฟรม จากนั้นใช้ requestAnimationFrame เพื่ออัปเดตพิกัด
blockAnimation: function () { var flag = 1; if (this.state) { // พิจารณาว่าจะรบกวนรูปภาพหรือกู้คืนรูปภาพ this.update(true) } else { flag = -1; ; } var self = this; this.startTime = +new Date(); // รับเวลาปัจจุบัน this.state = !this.state; (ฟังก์ชั่นแอนิเมชั่น() { var t = +new Date(); >= self.startTime + self.duration) { // เงื่อนไขสิ้นสุดแอนิเมชั่นส่งคืน false; } self.data.forEach (ฟังก์ชัน (รายการ, ดัชนี) { if (index % 2 == 0) { var pos = Math.tween.Expo. EaseInOut (t - self.startTime, 0, self.randoms [ดัชนี] * flag, self.duration); // คำนวณระยะทางที่เคลื่อนที่ในแต่ละเฟรม self.context.drawImage(self.img[self.index], item.x1 + pos, item.y1, self.wx, self.wy, item.x, item.y, self พื้นที่ self.area); } else { var pos = Math.tween.Expo.easeInOut(t - self.startTime, 0, self.randoms[index] * flag, self.duration); self.context.drawImage (self.img [self.index], item.x1, item.y1 + pos, self.wx, self.wy, item.x, item.y, self.area, self.area); } }); ขอAnimationFrame(ภาพเคลื่อนไหว);
ณ จุดนี้ แอนิเมชั่นการแยกและการฟื้นฟูได้ถูกนำมาใช้แล้ว
การสลับรูปภาพต่อไป เราจะเริ่มประมวลผลส่วนการสลับรูปภาพ ซึ่งก็เหมือนกับภาพแบบหมุน ภาพเคลื่อนไหวแบบหมุนจะย้ายตำแหน่งของแต่ละภาพตามความกว้างของหน้าต่างภาพ ความสูงเพื่อให้ได้ y การสลับบนแกน แตกต่างจากภาพหมุน เรามีแท็กผ้าใบเพียงอันเดียวที่นี่ เมื่อสลับ เราเพียงแต่ต้องเปลี่ยนพิกัดของรูปภาพปัจจุบันและรูปภาพถัดไป รูปภาพถัดไปคือ y1 + pos - imgHeight (ไปโดยไม่บอกว่าทำไม imgHeight จึงควรลดลง)
//ภาพเคลื่อนไหวแบบเลื่อนแนวตั้ง: function (val) { if (!this.time2) { return false; } this.checkTime(2); var self = this; val = 1 : val = -1; เลื่อนขึ้นหรือลงถ้า ((this.index + val) < 0 || (this.index + val) >= (this.img.length)) { // ตรวจสอบว่าหมายเลขซีเรียลของรูปภาพเป็นค่าสิ้นสุดหรือไม่ } นี้.รัฐ ? this.update(true) : this.update(false); this.startTime = +new Date(); (ฟังก์ชันแอนิเมชัน() { var t = +new Date(); if (t >= self.startTime + self .duration2) { val === 1 ? self.index++ : self.index--; // ปรับลำดับรูปภาพ self.index < 0 ? self.index = self.img.length - 1 : self.index; .ดัชนี >= self.img.length ? self.index = 0 : self.index; return false; } self.data.forEach (ฟังก์ชัน (รายการ) { var pos = Math.tween.Cubic.easeInOut (t - self.startTime, 0, (self.imgHeight) * val, self.duration2); // อัปเดตพิกัดรูปภาพปัจจุบัน self.context.drawImage (self.img [self.index], item.x1, item.y1 + pos, self.wx, self.wy, item.x, item.y, self.area, self.area); // อัปเดตพิกัดของภาพถัดไป self.context.drawImage(self.img[ self.index + val], item.x1, item.y1 + pos - self.imgHeight * val, self.wx, self.wy, item.x, item.y, self.area, self.area); }); requestAnimationFrame(ภาพเคลื่อนไหว); })() }
เช่นเดียวกับการสลับแกน x ตอนนี้คุณสามารถดูโค้ดทั้งหมดได้ใน codepen
ข้างต้นคือเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการศึกษาของทุกคน ฉันหวังว่าทุกคนจะสนับสนุน VeVb Wulin Network