【Share Code | HTML & CSS & Javascript】动画片段幻灯片
[查看demo & 下载资源](https://zhaoshuquan.com/posts/15
介绍
本文使用"Pieces"库轻松实现动画片段幻灯片效果。
今天我们想向您展示如何创建一个具有动画片段幻灯片效果的图片。 图片被分成多个片段,这些片段将以不同的方式进行动画制作,使用Pieces,可以轻松实现这些有趣的效果。
这将是最终结果:
动画由anime.js提供支持。
最初的想法
这种效果的灵感来源Dribbble的Shift动画:
开始使用Pieces
有关Pieces库的所有详细文档都可以在其Github存储库中找到。 但无论如何,让我们快速看到一些基本概念,以便能够开始使用这个库。
如果我们要绘制一个带有动画的图片,这些是构成场景的基本元素:
Pieces Basic Elements (Pieces基本元素)
如您所见,我们想要绘制的图像将是我们的项item,它被分成几个pieces,根据我们定义的选项,它们的大小和位置也可能不同。 要查看所有可能的选项,我建议您查看Github上的文档。
在整个教程中,我们将解释每段代码,以便您可以学习如何使用Pieces库实现自己的动画。 开始吧!
HTML 结构
在开始编写Javascript代码之前,让我们看看我们如何为slider定义HTML。 标记非常简单,因为我们每个幻灯片都有相应的图像和文本,canvas元素用于动画,而按钮用于浏览slider。
<!-- Pieces Slider -->
<div class="pieces-slider">
<!-- 每一个slider都有对应的图像和文本 -->
<div class="pieces-slider__slide">
<img class="pieces-slider__image" src="img/ricardo-gomez-angel-381749.jpg" alt="">
<div class="pieces-slider__text">Ricardo Gomez Angel</div>
</div>
<div class="pieces-slider__slide">
<img class="pieces-slider__image" src="img/josh-calabrese-527813.jpg" alt="">
<div class="pieces-slider__text">Josh Calabrese</div>
</div>
<div class="pieces-slider__slide">
<img class="pieces-slider__image" src="img/samuel-zeller-103111.jpg" alt="">
<div class="pieces-slider__text">Samuel Zeller</div>
</div>
<div class="pieces-slider__slide">
<img class="pieces-slider__image" src="img/sweet-ice-cream-photography-143023.jpg" alt="">
<div class="pieces-slider__text">Sweet Ice Cream</div>
</div>
<div class="pieces-slider__slide">
<img class="pieces-slider__image" src="img/sticker-mule-199237.jpg" alt="">
<div class="pieces-slider__text">Sticker Mule</div>
</div>
<!-- Canvas 绘制 pieces -->
<canvas class="pieces-slider__canvas"></canvas>
<!-- Slider 按钮: prev 和 next -->
<button class="pieces-slider__button pieces-slider__button--prev">prev</button>
<button class="pieces-slider__button pieces-slider__button--next">next</button>
</div>
设置slider的样式
需要一些特殊的样式来实现我们的效果。 我们需要隐藏图像和文本,因为我们将使用我们的库重绘它们。 但是如果没有可用的JavaScript,我们也希望它们回退到它们的初始标记。 最后,我们需要确保slider响应媒体查询:
.pieces-slider {
position: relative;
text-align: center;
padding: 8rem 0;
}
.js .pieces-slider {
padding: 0;
}
/* Make all slides absolutes and hide them */
.js .pieces-slider__slide {
position: absolute;
right: 100%;
}
/* Define image dimensions and also hide them */
.pieces-slider__image {
max-width: 600px;
max-height: 400px;
}
.js .pieces-slider__image {
visibility: hidden;
}
/* Hide the titles */
.js .pieces-slider__text {
text-indent: -9999px;
}
/* Canvas with viewport width and height */
.js .pieces-slider__canvas {
position: relative;
width: 100vw;
height: 100vh;
transition: 0.2s opacity;
}
/* Class for when we resize */
.pieces-slider__canvas--hidden {
opacity: 0;
transition-duration: 0.3s;
}
/* Navigation buttons */
.pieces-slider__button {
position: absolute;
left: 0;
top: 50%;
width: 100px;
height: 100px;
margin: -25px 0 0 0;
background-color: #5104ab;
color: #fff;
font-family: inherit;
font-weight: bold;
border: none;
cursor: pointer;
transition: 0.1s background-color;
}
.pieces-slider__button:hover {
background: #5f3abf;
}
.pieces-slider__button--next {
left: auto;
right: 0;
}
/* Hide the buttons when no JS */
.no-js .pieces-slider__button {
display: none;
}
/* Media queries with styles for smaller screens */
@media screen and (max-width: 720px) {
.pieces-slider__image {
max-width: 300px;
}
}
@media screen and (max-width: 55em) {
.pieces-slider__canvas {
width: 100vw;
height: 100vw;
}
.pieces-slider__button {
width: 60px;
height: 60px;
}
}
如您所见,我们隐藏了我们为滑块定义的HTML元素(按钮除外),因为我们将在canvas元素中绘制所有内容。
使用Pieces为slider设置动画
让我们定义一些变量并从DOM获取slider信息:
// Get all images and texts, get the `canvas` element, and save slider length
var sliderCanvas = document.querySelector('.pieces-slider__canvas');
var imagesEl = [].slice.call(document.querySelectorAll('.pieces-slider__image'));
var textEl = [].slice.call(document.querySelectorAll('.pieces-slider__text'));
var slidesLength = imagesEl.length;
然后我们需要定义索引变量来处理我们在画布上绘制的所有item:
// Define indexes related variables, as we will use indexes to reference items
var currentIndex = 0, currentImageIndex, currentTextIndex, currentNumberIndex;
var textIndexes = [];
var numberIndexes = [];
// Update current indexes for image, text and number
function updateIndexes() {
currentImageIndex = currentIndex * 3;
currentTextIndex = currentImageIndex + 1;
currentNumberIndex = currentImageIndex + 2;
}
updateIndexes();
现在我们将开始为每种类型的项目(图像,文本,数字和按钮)定义选项。 您可以在Pieces文档中找到完整的参考,这里详细解释了用于绘制图像的每个选项的作用:
// Options for images
var imageOptions = {
angle: 45, // rotate item pieces 45deg
extraSpacing: {extraX: 100, extraY: 200}, // this extra spacing is needed to cover all the item, because angle != 0
piecesWidth: function() { return Pieces.random(50, 200); }, // every piece will have a random width between 50px and 200px
ty: function() { return Pieces.random(-400, 400); } // every piece will be translated in the Y axis a random distance between -400px and 400px
};
同样,我们将为其他项类型定义选项。 请参阅注释以了解所使用的一些属性:
/ Options for texts
var textOptions = {
color: 'white',
backgroundColor: '#0066CC',
fontSize: function() { return windowWidth > 720 ? 50 : 30; },
padding: '15 20 10 20',
angle: -45,
extraSpacing: {extraX: 0, extraY: 300},
piecesWidth: function() { return Pieces.random(50, 200); },
ty: function() { return Pieces.random(-200, 200); },
translate: function() {
if (windowWidth > 1120) return {translateX: 200, translateY: 200};
if (windowWidth > 720) return {translateX: 0, translateY: 200};
return {translateX: 0, translateY: 100};
}
};
// Options for numbers
var numberOptions = {
color: 'white',
backgroundColor: '#0066CC',
backgroundRadius: 300,
fontSize: function() { return windowWidth > 720 ? 100 : 50; },
padding: function() { return windowWidth > 720 ? '18 35 10 38' : '18 25 10 28'; },
angle: 0,
piecesSpacing: 2,
extraSpacing: {extraX: 10, extraY: 10},
piecesWidth: 35,
ty: function() { return Pieces.random(-200, 200); },
translate: function() {
if (windowWidth > 1120) return {translateX: -340, translateY: -180};
if (windowWidth > 720) return {translateX: -240, translateY: -180};
return {translateX: -140, translateY: -100};
}
};
现在我们为每种类型的项目提供了所有选项,让它们放在一起将它传递给Pieces库!
// Build the array of items to draw using Pieces
var items = [];
var imagesReady = 0;
for (var i = 0; i < slidesLength; i++) {
// Wait for all images to load before initializing the slider and event listeners
var slideImage = new Image();
slideImage.onload = function() {
if (++imagesReady == slidesLength) {
initSlider();
initEvents();
}
};
// Push all elements for each slide with the corresponding options
items.push({type: 'image', value: imagesEl[i], options: imageOptions});
items.push({type: 'text', value: textEl[i].innerText, options: textOptions});
items.push({type: 'text', value: i + 1, options: numberOptions});
// Save indexes
textIndexes.push(i * 3 + 1);
numberIndexes.push(i * 3 + 2);
// Set image src
slideImage.src = imagesEl[i].src;
}
除了构建元素数组之外,在前面的代码块中,我们定义了一个简单的机制,只有在加载了所有图像时才调用initSlider函数。 这非常重要,因为我们无法使用Pieces绘制不可用的图像。
到目前为止,我们还没有画任何东西,但我们现在已经准备好了。 让我们看看我们如何初始化一个新的Pieces实例。
// Save the new Pieces instance
piecesSlider = new Pieces({
canvas: sliderCanvas, // CSS selector to get the canvas
items: items, // the Array of items we've built before
x: 'centerAll', // center all items in the X axis
y: 'centerAll', // center all items in the Y axis
piecesSpacing: 1, // default spacing between pieces
fontFamily: ["'Helvetica Neue', sans-serif"],
animation: { // animation options to use in any operation
duration: function() { return Pieces.random(1000, 2000); },
easing: 'easeOutQuint'
},
debug: false // set `debug: true` to enable debug mode
});
现在,所有的items和pieces都可以添加动画。 它们实际上已经创建的好了,但默认是隐藏的,所以,让我们看看如何显示第一张幻灯片并启动我们想要的动画:
// Animate all numbers to rotate clockwise indefinitely
piecesSlider.animateItems({
items: numberIndexes,
duration: 20000,
angle: 360,
loop: true
});
// Show current items: image, text and number
showItems();
因此,要显示和隐藏当前项目,我们需要分别调用showItems和hideItems函数。 我们已经实现了如下:
// Show current items: image, text and number
function showItems() {
// Show image pieces
piecesSlider.showPieces({items: currentImageIndex, ignore: ['tx'], singly: true, update: (anim) => {
// Stop the pieces animation at 60%, and run a new indefinitely animation of `ty` for each piece
if (anim.progress > 60) {
var piece = anim.animatables[0].target;
var ty = piece.ty;
anime.remove(piece);
anime({
targets: piece,
ty: piece.h_ty < 300
? [{value: ty + 10, duration: 1000}, {value: ty - 10, duration: 2000}, {value: ty, duration: 1000}]
: [{value: ty - 10, duration: 1000}, {value: ty + 10, duration: 2000}, {value: ty, duration: 1000}],
duration: 2000,
easing: 'linear',
loop: true
});
}
}});
// Show pieces for text and number, using alternate `ty` values
piecesSlider.showPieces({items: currentTextIndex});
piecesSlider.showPieces({items: currentNumberIndex, ty: function(p, i) { return p.s_ty - [-3, 3][i % 2]; }});
}
// Hide current items: image, text and number
function hideItems() {
piecesSlider.hidePieces({items: [currentImageIndex, currentTextIndex, currentNumberIndex]});
}
最后,为了浏览slides,我们已经定义了这些功能:
// Select the prev slide: hide current items, update indexes, and show the new current item
function prevItem() {
hideItems();
currentIndex = currentIndex > 0 ? currentIndex - 1 : slidesLength - 1;
updateIndexes();
showItems();
}
// Select the next slide: hide current items, update indexes, and show the new current item
function nextItem() {
hideItems();
currentIndex = currentIndex < slidesLength - 1 ? currentIndex + 1 : 0;
updateIndexes();
showItems();
}
因此,如果单击导航按钮或按下某些箭头键(向左或向右),我们需要调用这些函数:
// Select prev or next slide using buttons
prevButtonEl.addEventListener('click', prevSlide);
nextButtonEl.addEventListener('click', nextSlide);
// Select prev or next slide using arrow keys
document.addEventListener('keydown', function (e) {
if (e.keyCode == 37) { // left
prevSlide();
} else if (e.keyCode == 39) { // right
nextSlide();
}
});
我们差不多完成
【Share Code | HTML & CSS & Javascript】动画片段幻灯片的更多相关文章
- 一些非常有用的html,css,javascript代码片段(持久更新)
1.判断设备是否联网 if (navigator.onLine) { //some code }else{ //others code } 2.获取url的指定参数 function getStrin ...
- 惊人的CSS和JavaScript动画logos例子
https://codepen.io/lindell/pen/mEVgJP Stack Overflow logo是我最喜欢的logo之一,因为它非常简单,但易于识别.并且这个片段动画点击预览Stac ...
- 梅须逊雪三分白,雪却输梅一段香——CSS动画与JavaScript动画
CSS动画并不是绝对比JavaScript动画性能更优越,开源动画库Velocity.js等就展现了强劲的性能. 一.两者的主要区别 先开门见山的说说两者之间的区别. 1)CSS动画: 基于CSS的动 ...
- 利用 share code 插件同步代码片段
利用 Settings Sync可以同步 VS code 配置,但它只能同步插件,利用 Settings Sync 再配合 share code 插件可以同步自定义代码片段,可以把 VS code ...
- Javascript动画效果(一)
Javascript动画效果(一) 前面我们介绍了Javascript的回到顶部效果,今天呢,我们对Javascript动画做进一步的研究.在这篇博文中我们只介绍简单的匀速运动.简单的缓冲运动和简单的 ...
- Win10系列:JavaScript 动画1
在应用程序中使用动画会使应用显得更加生动,进而给用户带来良好的视觉效果.例如,当用户将某个项添加到列表时,新项不会立即出现在列表中,而是采用动画形式到达相应位置,并且列表中的其他项也采用动画形式移动到 ...
- CSS变形动画
CSS变形动画 前言 在开始介绍CSS变形动画之前,可以先了解一下学习了它之后能做什么,有什么用,这样你看这篇文章可能会有一些动力. 学习了CSS变形动画后,你可以为你的页面做出很多炫酷的效果,如一个 ...
- Javascript动画效果(三)
Javascript动画效果(三) 前面我们已经介绍了速度动画.透明度动画.多物体运动和任意值变化,并且我们在Javascript动画效果(二)中介绍到我们封装了一个简单的插件雏形,接下来我们对前面的 ...
- Javascript动画效果(二)
Javascript动画效果(二) 在前面的博客中讲了简单的Javascript动画效果,这篇文章主要介绍我在改变之前代码时发现的一些问题及解决方法. 在前面的多物体宽度变化的例子中,我们给其增加代码 ...
随机推荐
- 动态加载js不执行解决办法
这个问题的产生原因是:我们项目有一个主index文件,在主index文件中需要根据参数来判断是加载pc.html的内容还是加载mobile.html的内容,一开始是使用jquery来做的,没有问题,后 ...
- flask的session基础认识
from flask import Flask,session from datetime import timedelta import os app = Flask(__name__) app.c ...
- [转帖]英特尔首款采用10nm技术的混合CPU“Lakefield”即将发布
英特尔首款采用10nm技术的混合CPU“Lakefield”即将发布 intel 也出soc了 里面的东西 跟 安卓和 apple的a系列很像. https://baijiahao.baidu.com ...
- 石子合并2——区间DP【洛谷P1880题解】
[区间dp让人头痛……还是要多写些题目练手,抽空写篇博客总结一下] 这题区间dp入门题,理解区间dp或者练手都很妙 ——题目链接—— (或者直接看下面) 题面 在一个圆形操场的四周摆放N堆石子,现要将 ...
- Web项目测试流程总结
个人知识脑图总结 - 未完全(工作项目脑图总结存于网盘中)
- 深入理解计算机系统 第十二章 并发编程 part1 第二遍
三种构造并发程序的方法及其优缺点 1.进程 用这种方法,每个逻辑控制流都是一个进程,由内核来调度和维护.因为进程有独立的虚拟地址空间,想要和其他流通信,控制流必须使用某种显式的进程间通信机制. 优点: ...
- JavaScript设计模式(装饰者模式)
一.模拟传统面向对象语言的装饰者模式: 假设我们在编写一个飞机大战的游戏,随着经验值的增加,我们操作的飞机对象可以升级成更厉害的飞机,一开始这些飞机只能发射普通的子弹,升到第二级时可以发射导弹,升到第 ...
- CentOS7 yum安装Mariadb
1.安装Mariadb #yum -y install mariadb mariadb-server 1.1当执行程序末端显示Complete则完成安装 2.安装完成后启动服务 # systemctl ...
- 【原创】大数据基础之ETL vs ELT or DataWarehouse vs DataLake
ETL ETL is an abbreviation of Extract, Transform and Load. In this process, an ETL tool extracts the ...
- 学习笔记--三分法&秦九韶算法
前言 其实也没什么好说的吧,三分法就是用来求一个单调函数的最值和满足最大值的\(x\),秦九韶算法就是在\(O(N)\)时间内求一个多项式值 怎么用 三分法使用--看这篇:https://www.cn ...