js动画原理
1.匀速
2.碰撞
.box{height: 100px;width: 100px;background: #333;position: absolute;left: 0;right: 0;}
.box1{left: 500px;top: 500px;}
<input type="text" id="te">
<div class="box"></div><div class="box1"></div>
设定一些基础变量
var oText = document.getElementById("te");
var oDiv = document.querySelector(".box");
var oDiv2 = document.querySelector(".box1");
var speedX = 30;//设置div距离页面左边的距离
var speedY = 30;//设置div距离页面上边的距离
oDiv.speedX = 15;//设置div横向速度
oDiv.speedY = 3;//设置div纵向速度
oDiv2.speedX = 18;
oDiv2.speedY = 2;
function move(el){
var currentLeft = parseInt(window.getComputedStyle(el).left);//取得元素当前距离父元素左边的距离
var currentTop = parseInt(window.getComputedStyle(el).top);//取得元素当前距离父元素上边的距离
check_border_conllision(el);//引用下边的构造函数判断元素是否到达了页面边缘
var left = currentLeft + el.speedX;//设置一个速度让div距离页面左边的位置
var top = currentTop + el.speedY;
el.style.left = left + ‘px‘;//将取得速度后的距离父元素的左边距离赋值给元素
el.style.top = top + ‘px‘;
}
盒子碰撞到了页面边缘检测核心构造函数
function check_border_conllision(el){
var elStyle = window.getComputedStyle(el);
var left = parseInt(elStyle.left);
var top = parseInt(elStyle.top);
var w = parseInt(elStyle.width);//div的宽度
var h = parseInt(elStyle.height);
if(left < 0){//如果左侧位置是负值,则将它设为0,平移值转换
left = 0;
el.speedX *= -1;
}
if(left > window.innerWidth - w){//如果现在的左侧距离大于了页面宽度减去div的宽度,表示右边已经撞上了。
left = window.innerWidth -w;
el.speedX *= -1;
}
if(top < 0){
top = 0;
el.speedY *= -1;
}
if(top > window.innerHeight - h){
top = window.innerHeight - h;
el.speedY *= -1;
}
el.style.left = left + ‘px‘;
el.style.top = top + ‘px‘;
}
检测两个盒子相撞核心构造函数
function check_conllision(el,el2){
var style1 = window.getComputedStyle(el);
var style2 = window.getComputedStyle(el2);
var left1 = parseInt(style1.left);
var left2 = parseInt(style2.left);
var top1 = parseInt(style1.top);
var top2 = parseInt(style2.top);
var w1 = parseInt(style1.width);
var w2 = parseInt(style2.width);
var h1 = parseInt(style1.height);
var h2 = parseInt(style2.height);
var style1Zx = {x:left1 + w1 / 2,y:top1 + h1 / 2};//箱子1的中心点位置
var style2Zx = {x:left2 + w2 / 2,y:top2 + h2 / 2};//箱子2的中心点位置
var leftc = Math.abs(style1Zx.x - style2Zx.x);//取绝对值
var topc = Math.abs(style1Zx.y - style2Zx.y);
if(leftc <= (w1 + w2)/2 && topc <= (h1 + h2)/2){//如果箱子的中心点小于他们的高度和宽度一半之和,我们判断为相撞
return true;
}
return false;
}
function move2(el){
var currentLeft = parseInt(window.getComputedStyle(el).left);
var currentTop = parseInt(window.getComputedStyle(el).top);
check_border_conllision(el);
var tempX, tempY;
if(check_conllision(oDiv,oDiv2)){//判断是否相撞,将箱子的速度互换
tempX = oDiv.speedX;
tempY = oDiv.speedY;
oDiv.speedX = oDiv2.speedX;
oDiv.speedY = oDiv2.speedY;
oDiv2.speedX = tempX;
oDiv2.speedY = tempY;
}
var left = currentLeft + el.speedX;//设置div距离页面左边的位置
var top = currentTop + el.speedY;
el.style.left = left + ‘px‘;
el.style.top = top + ‘px‘;
}
setInterval(() => {
move2(oDiv);move2(oDiv2);
}, 20);
动画函数的封装
1.getStyle
2.减速
3.透明度
4.多属性
var oDiv = document.querySelector("div");
function getStyle(el,property){//ie8兼容性
return el.currentStyle ? el.currentStyle[property] :window.getComputedStyle(el)[property];
}
function animateEl(el,properties){
clearInterval(el.timer);
let el.timer = setInterval(function() {//设定周期调用函数
for(var property in properties){//遍历对象中的键名
var curpro;
var target = properties[property];
if(property == "opacity"){
curpro = Math.round(parseFloat(getStyle(el,property)) * 100);//将值乘以100取整,方便计算speed
target = parseFloat(target)*100;
}else{
curpro = parseFloat(getStyle(el,property));console.log(curpro);//width如果使用parseInt,不会得到指定值,其他可以
}
var speed = (target - curpro) / 30;//目标距离减去当前距离除以30作为速度。
speed = speed > 0 ? Math.ceil(speed): Math.floor(speed);//如果速度大于0,则向上取整,至少为1,相反为-1;
if(property == "opacity"){
el.style[property] =(curpro + speed)/100 ;
}else{
el.style[property] =curpro + speed + "px";
}
if(parseInt(el.style[property]) === target){//因为对象有多个键值对,还没想好用什么办法匹配所有的值来让调用函数停止
//clearInterval(timer);
}
}
}, 20);
}
animateEl(oDiv,{"top":300,"width":300,"opacity":0.5});
自己写的
var speedCa = (opacity1 - targetFL)/30 ;
speedCa = speedCa / 100;
speedCa.toFixed(8);//如果指定值和现值很接近,则速度将会很小,所以先取小数点后面8个数,
el.style[property] = opacity1/100 - speedCa;
if(parseFloat(el.style[property]).toFixed(2) == parseFloat(target).toFixed(2)){//如果已经很接近,则直接将指定值赋值给现值
el.style[property] = target;
clearInterval(timer1);
}
轮播
1.透明度
*/
var preIndex,nextIndex,len,id;//当前页赋值给这个数,当前显示页面,图片总数,
var ul2li = document.querySelectorAll(".ul2 li");//全局对象圆点跳转图片
init();
function init(){//初始化
preIndex = nextIndex = 0;
len = document.querySelectorAll(".ul1 .item").length;
document.querySelector(".next").onclick = function(){//点击右侧一下张
slideNext();
}
document.querySelector(".pre").onclick = function(){
slidePre();
}
var slideImg = document.querySelector(".slideimg");
slideImg.onmouseover = function(){//鼠标悬停
stop();
}
slideImg.onmouseout = function(){
sildeAuto();
}
sildeAuto();//自动轮播
//点击下面的圆点跳转图片
for(i = 0; i < ul2li.length ; i++){//遍历所有的圆点
ul2li[i].index = i;//将当前的下标赋值给index
ul2li[i].onclick = function(){
preIndex = nextIndex;
nextIndex = this.index;
slideTo(preIndex,nextIndex);
}
}
}
function sildeAuto(){//3秒自动轮播
clearInterval(id);
id = setInterval(function(){
slideNext();
},3000);
}
function slidePre(){//向前封装函数
preIndex = nextIndex;
nextIndex--;
if(nextIndex === - 1){
nextIndex = len - 1;
}
slideTo(preIndex,nextIndex);
}
function slideNext(){//向后封装函数
preIndex = nextIndex;
nextIndex++;
if(nextIndex === len){
nextIndex = 0;
}
slideTo(preIndex,nextIndex);
}
function stop(){//停止周期调用函数
clearInterval(id);
}
function slideTo(pre,next){//透明度函数封装
var item = document.querySelectorAll(".ul1 .item");
ul2li[pre].className = "li";
ul2li[next].className = "li focus";
animateEl(item[pre],{opacity:0});
animateEl(item[next],{opacity:1});
}
//2.水平
var sIndex,len,liWidth,liItem,idin;
var list = document.querySelector(".slideimg2 .list");
var dot = document.querySelectorAll(".slideimg2 .list2 .dot");
init()
function init(){
sIndex = 1;
var newLi1 = document.querySelector(".slideimg2 .list .item:first-of-type");
var copy1 = newLi1.cloneNode(true);//复制第一张图片
var newLi4 = document.querySelector(".slideimg2 .list .item:last-of-type").cloneNode(true);
var copyLast = newLi4.cloneNode(true);//复制最后一张图片
list.appendChild(copy1);//将第一张图片添加到最后一个
list.insertBefore(copyLast,newLi1);//将最后一张图片添加到第一个
liItem = document.querySelectorAll(".list .item");
var liStyle = window.getComputedStyle(liItem[0]);
liWidth = liStyle.width;//取到一个li的宽度
list.style.left = -parseInt(liWidth) + "px";//让图片显示初始值第一个
len = liItem.length;//取到总li的个数
list.style.width = parseInt(liWidth) * len +"px";//list的宽度=li个数乘以li的宽度,让所有图片横排
//左按钮播放一下张图片
document.querySelector(".slideimg2 .preimg").onclick = function(){
preImg();
}
//右按钮播放一下张图片
document.querySelector(".slideimg2 .nextimg").onclick = function(){
nextImg();
}
//鼠标悬停
document.querySelector(".slideimg2").onmouseover = function(){
stop();
}
//鼠标离开自动轮播
document.querySelector(".slideimg2").onmouseout = function(){
auto();
}
auto();
//小圆点逻辑
for(var i = 0; i < dot.length ; i++){
dot[i].index = i;//将下标占时存入index
dot[i].onclick = function(){
sIndex = this.index + 1;//因为按钮的下一页前后都多了一张图片,所以小圆点的下标要加1,
sliTo(sIndex);
}
}
}
function auto(){//调用函数
clearInterval(idin);
idin = setInterval(function(){
nextImg();
},3000);
}
function stop(){
clearInterval(idin);//停止周期调用函数
}
function preImg(){
sIndex--;
if(sIndex === -1){//如果上一张图片到了第一张,则直接跳转到后面相同的图片
sIndex = len -3;
list.style.left = -parseInt(liWidth) * 4 + "px";
}
sliTo(sIndex);
}
function nextImg(){
sIndex++;
if(sIndex === len){//如果下一张图片到了最后一张,则直接跳转到前面相同的图片,
sIndex = 2;
list.style.left = -parseInt(liWidth) + "px";
}
sliTo(sIndex);
}
function sliTo(index){//滚动核心
js动画练习
原文:https://www.cnblogs.com/solaris-wwf/p/11630092.html