Просматривая CSSDesignAwards, я нашел эффект, который разделяет содержимое изображения (сайт: https://weareludwig.com). Вы можете нажать на него, чтобы посмотреть. Это было очень круто, поэтому я попытался реализовать его сам. и эффект был очень хороший. Проверьте эффект https://codepen.io/geeknoble/pen/OQaOVG
анализироватьВо-первых, мы можем обнаружить, что содержимое изображения разделено на маленькие прямоугольники, и каждый прямоугольник переводится случайным образом. Функция drawImage класса Canvas может обрезать содержимое изображения и нарисовать его на холсте Canvas, поэтому основным принципом реализации этого эффекта является использование drawImage. Существует два основных эффекта: один — прерывание и восстановление содержимого изображения, а другой — переключение на следующее изображение. DrawImage можно использовать для обоих эффектов, но расстояние перемещения разное. Когда у вас появится общая идея, можно приступать к ее реализации.
начальная работаСначала нам нужно инициализировать некоторые переменные, такие как ширина и высота изображения, количество прямоугольников, размер обрезки и т. д., затем вычислить координаты каждого прямоугольника и использовать двойной цикл для сохранения координат прямоугольника в данных. . Каждый прямоугольник имеет случайное смещение. Это смещение также необходимо сохранить и сохранить в случайном порядке. Среди них x и y представляют собой координаты холста, а x1 и y1 представляют собой координаты обрезки изображения.
init: function (context, width, height, area, img) { this.context = context; this.img = img; this.imgWidth = img[0].width; //Ширина и высота изображения this.imgHeight = img[ 0 ].height; this.index = 0; //Номер текущего изображения this.width = width; //Ширина и высота холста this.height = height; this.area = height/12; //Длина маленького прямоугольника this.countX = width/this.area //Количество маленьких прямоугольников по горизонтали и вертикали this.countY = height/this.area; .countX; //Ширина и высота изображения в маленьком прямоугольнике this.wy = this.imgHeight / this.countY; //Состояние изображения, true означает отсутствие разделения this.dataFlag = true; состояние координат, true означает, что случайное значение this.duration не добавляется = 1000; //Время анимации this.duration2 = 1500; this.startTime = 0; this.data = []; //Информация о координатах маленького прямоугольника this.randoms = []; //Инициализация координат прямоугольника var x1 = 0, y1 = 0, x = 0, y = 0; for (var i = 0; i < this.countY; i++) { for (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; } x1 = 0; wy; х = 0; y += this.area } this.checkMargin();Обнаружение краев
Прежде чем добавлять смещение к прямоугольнику, нам нужно определить, превышают ли смещенные координаты пределы изображения. Например, если прямоугольник вверху перемещается по оси Y, он может двигаться только вверх. текущая координата плюс значение смещения меньше 0 или больше ширины и высоты изображения. Если обновленные координаты меньше 0, то случайное значение должно быть отрицательным числом. Вам необходимо изменить случайное значение на положительное число. Если оно больше высоты изображения, измените его на отрицательное число. Поскольку каждый прямоугольник движется в одном направлении, я пишу здесь, что биты с четными номерами перемещают ось X, а биты с нечетными номерами перемещают ось Y.
// Обнаружение края checkMargin: function () { var self = this.data.forEach(function (item, index) { if (index % 2 == 0) { // Перемещаем ось X, если индекс равен a. кратно 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[index] < 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.data.forEach(function (item, index) { if (index % 2 == 0) { // Перемещаем ось X, если индекс равен a. кратно 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[index] < 0) self.randoms[index] = -self.randoms[index]; if (item.y1 + self.randoms[index] + self.wy > self.imgHeight) self.randoms[index] = -Math.abs(self.randoms[index]) } }) }
После сохранения координат вы можете реализовать анимацию перемещения. Процесс движения имеет плавный переход. Мы можем использовать алгоритм замедления Tween.js. Этот алгоритм имеет 4 параметра: текущее время, начальное положение и конечное положение. время анимации. Подробную информацию можно найти в статье Чжан Синьсюя 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; (functionanimation() { var t = +new Date(); if (t) >= self.startTime + self.duration) { // Условие завершения анимации return false } self.data.forEach(function (item, index) { if (index % 2 == 0) { var pos = Math.tween.Expo. easyInOut(t - self.startTime, 0, self.randoms[index] * flag, self.duration); // Вычислить расстояние, пройденное в каждом кадре self.context.drawImage(self.img[self.index], item.x1 + pos, item.y1, self.wx, self.wy, item.x, item.y, self. area, 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, а также расстояние перемещения. следующая картинка y1 + pos — imgHeight (само собой разумеется, почему imgHeight нужно уменьшить).
// Вертикальная скользящая анимацияverticalAnimation: function (val) { if (!this.time2) { return false } this.checkTime(2); val ? val = 1 : val = -1; Слайд вверх или вниз if ((this.index + val) < 0 || (this.index + val) >= (this.img.length)) { // Определяем, является ли серийный номер изображения конечным return false } это.состояние ? 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(function (item) { 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.