学废了家人们
建议作为艺术品鉴赏吧,等有能力在完全搞定!!!
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.div1{
width: 900px;
height: 300px;
}
</style>
</head>
<body>
<button>按钮</button>
<div class="div1"></div>
<script type="module">
import Carousel from "./js/Carousel.js";
var arr=[
{
id:1001,img:"./img/a.jpg",date:"28/Jul/2022",info:"与父母的47天自驾游|向疆而行2万里,我们依旧是过客"},
{
id:1002,img:"./img/b.jpg",date:"27/Jul/2022",info:"自驾川西小环线,在千碉之国遇见梨花如雪的季节"},
{
id:1003,img:"./img/c.jpg",date:"26/Jul/2022",info:"被误解的沙县,原来有这么多美食只有在当地才能吃到!"},
{
id:1004,img:"./img/d.jpg",date:"25/Jul/2022",info:"周末出逃计划 | 打卡美丽中国"},
{
id:1005,img:"./img/e.jpg",date:"24/Jul/2022",info:"寻迹山川湖海,邂逅云南的冬与夏"},
]
var list=[
{
id:1006,img:"./img/a2.jpg",date:"2/Nov.2021",info:"食欲拯救计划|阿一古~是贼拉好吃的延吉啊!"},
{
id:1007,img:"./img/b2.jpg",date:"1/Nov.2021",info:"徽州古村落赏秋自驾9日攻略!给这个秋天一个说走就走的理由!"},
{
id:1008,img:"./img/c2.jpg",date:"31/Oct.2021",info:"致,荆棘鸟与淘金先驱者——三赴西澳自驾笔记"},
{
id:1009,img:"./img/d2.jpg",date:"30/Oct.2021",info:"我是你的俘虏【跟新疆私奔】"},
{
id:1010,img:"./img/e2.jpg",date:"29/Oct.2021",info:"遇见阳朔的光与影,晨与昏,山与水"},
{
id:1011,date:"12/Jul.2021",info:"No Fear in My Heart. 10天4700公里,自由散漫南疆奇遇记。",img:"./img/a1.jpeg"},
{
id:1012,date:"11/Jul.2021",info:"128座乐园!284座过山车!我的全球乐园打卡计划持续更新ing",img:"./img/b1.jpg"},
{
id:1013,date:"10/Jul.2021",info:"带着父母旅行的第四年,疫情下的Flag小旗在广州飘~谢谢你们陪着我,会勇敢坚定的走自己的路",img:"./img/c1.jpg"},
{
id:1014,date:"09/Jul.2021",info:"念念闽夏|日子娓娓,一如夏季绵长",img:"./img/d1.jpg"},
{
id:1015,date:"08/Jul.2021",info:"30天自驾16座城市,从南到北,一万公里重新认识你。(海南-内蒙古-海南)",img:"./img/e1.jpg"},
]
// var carousel=new Carousel();
// carousel.setData(arr);//设置数据,没有数据之前,这个轮播图没有图片和小圆点
// carousel.appendTo("body");//没有放在页面上之前 offsetWidth offsetLeft一概不能获取到
// animation();
// function animation(){
// requestAnimationFrame(animation);
// carousel.update();
// }
// var bn=document.querySelector("button");
// bn.addEventListener("click",clickHandler);
// function clickHandler(e){
// carousel.setData(list);
// }
var c1=new Carousel(arr);
c1.appendTo(".div1");
var c2=new Carousel(list);
c2.appendTo("body");
animation();
function animation(){
requestAnimationFrame(animation);
Carousel.update();
}
</script>
</body>
</html>
Utils.js
export default class Utils{
static setCSS(css){
if(document.styleSheets.length===0 || !Array.from(document.styleSheets).some(item=>item.ownerNode.id==="defined")){
var style=document.createElement("style");
style.innerHTML=css;
style.id="defined"
document.head.appendChild(style);
return;
}
var styleSheet=Array.from(document.styleSheets).find(item=>item.ownerNode.id==="defined");
var arr=css.split(/(?<=\})/).map(item=>item.trim());
arr.forEach(item=>{
styleSheet.insertRule(item,styleSheet.cssRules.length);
})
}
static createElement(type,className,parent){
if(typeof parent==="string") parent=document.querySelector(parent);
var elem=document.createElement(type);
if(className) elem.className=className;
if(parent instanceof HTMLElement) parent.appendChild(elem);
return elem;
}
}
component.js
export default class Component{
elem;
constructor(type){
this.elem=document.createElement(type);
}
appendTo(parent){
if(typeof parent==="string") parent=document.querySelector(parent);
parent.appendChild(this.elem);
return parent;
}
insertTo(parent,nextElement){
if(typeof parent==="string") parent=document.querySelector(parent);
if(typeof nextElement==="string") nextElement=document.querySelector(nextElement);
if(parent instanceof HTMLElement && nextElement instanceof HTMLElement)
parent.insertBefore(this.elem,nextElement);
}
}
Carousel.js
import Component from "./Component.js";
import Utils from "./Utils.js";
export default class Carousel extends Component{
static MAX_TIME=200;
LEFT=Symbol();
RIGHT=Symbol();
imgCon;
left;
right;
dot;
list;
prev;
direction;
pos=0;
speed=50;
x=0;
autoBool=false;
time;
blockList={
};
bool=false;
static carouselList=new Set();
static cssBool=false;
constructor(_list){
super("div");
this.direction=this.LEFT;
this.time=Carousel.MAX_TIME;
this.elem.className="carousel";
this.imgCon=Utils.createElement("div","img-con",this.elem);
this.dot=Utils.createElement("ul","dot",this.elem);
this.left=Utils.createElement("canvas","left",this.elem);
this.right=Utils.createElement("canvas","right",this.elem);
this.left.width=this.right.width=30;
this.left.height=this.right.height=60;
this.drawBn(this.left,this.LEFT);
this.drawBn(this.right,this.RIGHT);
if(_list) this.setData(_list);
Carousel.carouselList.add(this);
this.elem.addEventListener("click",e=>this.clickHandler(e));
this.elem.addEventListener("mouseenter",e=>this.mouseHandler(e))
this.elem.addEventListener("mouseleave",e=>this.mouseHandler(e))
if(!Carousel.cssBool) Carousel.setStyle();
}
mouseHandler(e){
this.autoBool=e.type==="mouseleave";
this.time=Carousel.MAX_TIME;//设置时间恢复最大间隔时间
}
appendTo(parent){
parent=super.appendTo(parent);
if(parent.nodeName==="BODY") this.elem.style.height="33.3vw";
else this.elem.style.height="100%";
}
setData(_list){
if(!Array.isArray(_list))return;
// 清除上一次设置轮播图里面的内容
this.imgCon.innerHTML="";
this.list=null;
this.blockList=null;
this.blockList={
};
this.list=_list;
this.dot.innerHTML=this.list.reduce(v=>v+"<li></li>","");
this.imgCon.appendChild(this.getImgBlock(this.list[this.pos]))
this.changePrev();
}
getImgBlock(data){
// 在存储对象中查找有没有当前数据id作为key存储内容,如果有直接返回
if(this.blockList[data.id]) return this.blockList[data.id];
// 传递div
var div=document.createElement("div");
div.className="img-block"
// 根据数据设置这个div中的内容
div.innerHTML=`
<img src="${
data.img}">
<div>
<span><i>${
data.date.split("/").shift()}</i>${
data.date.match(/\/.*/)[0].replace(/\/(?=\d+)/,".")}</span>
<h1>${
data.info}</h1>
</div>
`
// 将创建好的div用id作为key存储在存储对象中
this.blockList[data.id]=div;
// 返回创建好的div
return div;
}
drawBn(elem,direction){
var ctx = elem.getContext("2d");
ctx.fillStyle = "white"
ctx.beginPath();
ctx.moveTo(4, 31);
ctx.lineTo(22, 9);
ctx.lineTo(21, 17);
ctx.lineTo(12, 30);
ctx.lineTo(21, 43);
ctx.lineTo(22, 51);
ctx.closePath();
ctx.fill();
if(direction===this.RIGHT) elem.style.transform = "scale(-1,1) translate(0px, -50%)";
}
clickHandler(e){
if(this.bool) return;
// 如果className不是left或者right,并且被点击的元素也不是LI 跳出
if(!/left|right/.test(e.target.className) && e.target.nodeName!=="LI") return;
if(e.target.className==="left"){
// 如果点击按钮是左按钮
this.direction=this.RIGHT;
// pos递减,并且如果pos是最前面时,让pos为最后一个
if(--this.pos<0)this.pos=this.list.length-1;
}else if(e.target.className==="right"){
// 如果点击按钮是右按钮
this.direction=this.LEFT;
// pos递加,如果pos是最后一个,让pos为第一个
if(++this.pos>this.list.length-1) this.pos=0;
}else{
// 根据当前点击li是父容器的所有子元素中的第几个获取到点击的索引
var index=Array.from(e.target.parentElement.children).indexOf(e.target);
// 如果点击的索引就是当前的显示的索引,跳出
if(this.pos===index) return;
// 如果点击的索引大于当前的索引,设置方向为LEFT,否则设置为RIGHT
this.direction= index>this.pos ? this.LEFT : this.RIGHT;
// 并且将点击的索引重新赋值给当前索引
this.pos=index;
}
this.changePrev();
this.createNextImg();
}
changePrev(){
if(this.prev){
this.prev.style.backgroundColor="transparent"
}
this.prev=this.imgCon.nextElementSibling.children[this.pos];
this.prev.style.backgroundColor="red";
}
createNextImg(){
if(this.direction===this.LEFT){
// 将当前点击的要变化的索引对应div获取插入在容器的尾部
this.imgCon.appendChild(this.getImgBlock(this.list[this.pos]));
this.x=0;
}else{
// 将需要变化索引的图片插入在轮播容器的最前面
this.imgCon.insertBefore(this.getImgBlock(this.list[this.pos]),this.imgCon.firstElementChild);
this.x=-this.imgCon.offsetWidth/2;
}
// 并且重新设置轮播容器位置
this.imgCon.style.left=this.x+"px";
this.bool=true;
}
update(){
this.imgMove();
this.autoPlay();
}
static update(){
Carousel.carouselList.forEach(item=>item.update())
}
imgMove(){
// 如果bool是非,就不进入动画,这个bool控制是否进入动画
if(!this.bool) return;
if(this.direction===this.LEFT){
// 如果方向向左走,让x不断递减
this.x-=this.speed;
// 如果容器已经向左运行一半时
if(this.x<=-this.imgCon.offsetWidth/2){
// 停止动画
this.bool=false;
// 删除第一个图片,第二张掉在前面去,
this.imgCon.firstElementChild.remove();
// 这时候将整体重新挪回到0的位置
this.x=0;
}
}else{
// 如果方向向右走,让x不断递加
this.x+=this.speed;
if(this.x>=0){
// 当x大于等于0,让动画停止
this.bool=false;
// 并且删除最后一张图片
this.imgCon.lastElementChild.remove();
// 这时候将整体重新挪回到0的位置
this.x=0;
}
}
// 设置改变图片容器的位置
this.imgCon.style.left=this.x+"px";
}
autoPlay(){
// 如果自动轮播没有开启就跳出
// 如果自动轮播开启,但是time递减后大于0,则跳出
if(!this.autoBool || --this.time>0)return;
// 设置当前间隔时间为最大
this.time=Carousel.MAX_TIME;
// 向right按钮抛发点击事件,触发轮播
var evt=new MouseEvent("click",{
bubbles:true});
this.imgCon.parentElement.lastElementChild.dispatchEvent(evt);
}
static setStyle(){
Carousel.cssBool=true;
Utils.setCSS(` body{
margin: 0;
padding: 0;
}
.carousel{
width: 100%;
position: relative;
left: 0;
top: 0;
font-size: 0;
min-width: 1000px;
overflow: hidden;
}
.carousel>.img-con{
width: 200%;
height: 100%;
position: absolute;
left: 0;
}
.carousel .img-block{
width: 50%;
height: 100%;
position: relative;
float: left;
}
.carousel .img-block>img{
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
}
.carousel .img-block>div{
position: absolute;
left:10vw;
top: 2vw;
font-size: 20px;
color: white;
}
.carousel .img-block>div>span>i{
font-style:normal;
font-size: 28px;
}
.carousel .img-block>div>h1{
font-size: 20px;
}
.clear::after
{
content: "";
display: block;
visibility: hidden;
height: 0;
overflow: hidden;
clear: both;
}
ul{
list-style: none;
position: absolute;
bottom: 3vw;
left: 50%;
transform: translate(-50%,0);
}
ul li{
width: 1.6vw;
height: 1.6vw;
border:2px solid red;
margin-left: 1.3vw;
float: left;
border-radius: 1.6vw;
}
.left,.right{
position: absolute;
top: 50%;
transform: translate(0,-50%);
}
.left{
left: 3vw;
}
.right{
right: 3vw;
}`)
}
}