You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
205 lines
6.1 KiB
205 lines
6.1 KiB
|
3 weeks ago
|
const app = getApp();
|
||
|
|
/**
|
||
|
|
* >=min && <=max
|
||
|
|
* @param min
|
||
|
|
* @param max
|
||
|
|
*/
|
||
|
|
function getRandom(min, max) {
|
||
|
|
return min + Math.floor(Math.random() * (max - min + 1));
|
||
|
|
}
|
||
|
|
Component({
|
||
|
|
options: {},
|
||
|
|
lifetimes: {
|
||
|
|
attached() {
|
||
|
|
const query = wx.createSelectorQuery().in(this);
|
||
|
|
query
|
||
|
|
.select("#thumsCanvas")
|
||
|
|
.fields({ node: true, size: true })
|
||
|
|
.exec((res) => {
|
||
|
|
const canvas = res[0].node;
|
||
|
|
const context = canvas.getContext("2d");
|
||
|
|
this.setData({
|
||
|
|
context: context,
|
||
|
|
});
|
||
|
|
|
||
|
|
const dpr = wx.getSystemInfoSync().pixelRatio;
|
||
|
|
canvas.width = res[0].width * dpr;
|
||
|
|
canvas.height = res[0].height * dpr;
|
||
|
|
this.data.width = res[0].width * dpr;
|
||
|
|
this.data.height = res[0].height * dpr;
|
||
|
|
// context.fillStyle = "rgba(255, 255, 255, 0)";
|
||
|
|
const images = [
|
||
|
|
"star/icon1.png?r=1",
|
||
|
|
"star/icon2.png?r=1",
|
||
|
|
"star/icon3.png?r=1",
|
||
|
|
"star/icon4.png?r=1",
|
||
|
|
"star/icon5.png?r=1",
|
||
|
|
"star/icon6.png?r=1",
|
||
|
|
"star/icon7.png?r=1",
|
||
|
|
"star/icon8.png?r=1",
|
||
|
|
];
|
||
|
|
const promiseAll = [] as Array<Promise<any>>;
|
||
|
|
images.forEach((src) => {
|
||
|
|
const p = new Promise(function (resolve) {
|
||
|
|
const img = canvas.createImage();
|
||
|
|
img.onerror = img.onload = resolve.bind(null, img);
|
||
|
|
img.src = app.globalData.imageUrl + src;
|
||
|
|
});
|
||
|
|
promiseAll.push(p);
|
||
|
|
});
|
||
|
|
Promise.all(promiseAll).then((imgsList) => {
|
||
|
|
const imgsLists = imgsList.filter((d) => {
|
||
|
|
if (d && d.width > 0) return true;
|
||
|
|
return false;
|
||
|
|
});
|
||
|
|
this.setData({
|
||
|
|
imgsList: imgsLists,
|
||
|
|
});
|
||
|
|
if (this.data.imgsList.length == 0) {
|
||
|
|
// logger.error("imgsList load all error");
|
||
|
|
wx.showToast({
|
||
|
|
icon: "none",
|
||
|
|
title: "imgsList load all error",
|
||
|
|
});
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
});
|
||
|
|
},
|
||
|
|
},
|
||
|
|
properties: {},
|
||
|
|
data: {
|
||
|
|
imgsList: [] as WechatMiniprogram.ImageData[],
|
||
|
|
width: 0,
|
||
|
|
height: 0,
|
||
|
|
context: null as any,
|
||
|
|
scanning: false,
|
||
|
|
renderList: [],
|
||
|
|
scaleTime: 0.1, // 百分比
|
||
|
|
},
|
||
|
|
methods: {
|
||
|
|
handleTap() {
|
||
|
|
this.start();
|
||
|
|
},
|
||
|
|
createRender() {
|
||
|
|
if (this.data.imgsList.length == 0) return null;
|
||
|
|
const basicScale = [0.4, 0.5, 0.6][getRandom(0, 2)];
|
||
|
|
|
||
|
|
const getScale = (diffTime) => {
|
||
|
|
if (diffTime < this.data.scaleTime) {
|
||
|
|
return +(diffTime / this.data.scaleTime).toFixed(2) * basicScale;
|
||
|
|
} else {
|
||
|
|
return basicScale;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
const context = this.data.context;
|
||
|
|
// 随机读取一个图片来渲染
|
||
|
|
const image: any = this.data.imgsList[getRandom(0, this.data.imgsList.length - 1)];
|
||
|
|
const offset = 20;
|
||
|
|
const basicX = this.data.width / 2 + getRandom(-offset, offset);
|
||
|
|
const angle = getRandom(2, 10);
|
||
|
|
let ratio = getRandom(10, 30) * (getRandom(0, 1) ? 1 : -1);
|
||
|
|
const getTranslateX = (diffTime) => {
|
||
|
|
if (diffTime < this.data.scaleTime) {
|
||
|
|
// 放大期间,不进行摇摆位移
|
||
|
|
return basicX;
|
||
|
|
} else {
|
||
|
|
return basicX + ratio * Math.sin(angle * (diffTime - this.data.scaleTime));
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
const getTranslateY = (diffTime) => {
|
||
|
|
return image.height / 2 + (this.data.height - image.height / 2) * (1 - diffTime);
|
||
|
|
};
|
||
|
|
|
||
|
|
const fadeOutStage = getRandom(14, 18) / 100;
|
||
|
|
const getAlpha = (diffTime) => {
|
||
|
|
let left = 1 - +diffTime;
|
||
|
|
if (left > fadeOutStage) {
|
||
|
|
return 1;
|
||
|
|
} else {
|
||
|
|
return 1 - +((fadeOutStage - left) / fadeOutStage).toFixed(2);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
return (diffTime) => {
|
||
|
|
// 差值满了,即结束了 0 ---》 1
|
||
|
|
if (diffTime >= 1) return true;
|
||
|
|
context.save();
|
||
|
|
const scale = getScale(diffTime);
|
||
|
|
// const rotate = getRotate();
|
||
|
|
const translateX = getTranslateX(diffTime);
|
||
|
|
const translateY = getTranslateY(diffTime);
|
||
|
|
context.translate(translateX, translateY);
|
||
|
|
context.scale(scale, scale);
|
||
|
|
// context.rotate(rotate * Math.PI / 180);
|
||
|
|
context.globalAlpha = getAlpha(diffTime);
|
||
|
|
context.drawImage(image, -image.width / 2, -image.height / 2, image.width, image.height);
|
||
|
|
context.restore();
|
||
|
|
};
|
||
|
|
},
|
||
|
|
scan() {
|
||
|
|
this.data.context.clearRect(0, 0, this.data.width, this.data.height);
|
||
|
|
this.data.context.fillStyle = "rgba(255, 255, 255, 0)";
|
||
|
|
this.data.context.fillRect(0, 0, 200, 400);
|
||
|
|
let index = 0;
|
||
|
|
let length = this.data.renderList.length;
|
||
|
|
if (length > 0) {
|
||
|
|
this.requestFrame(this.scan.bind(this));
|
||
|
|
this.setData({
|
||
|
|
scanning: true,
|
||
|
|
});
|
||
|
|
} else {
|
||
|
|
this.setData({
|
||
|
|
scanning: false,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
while (index < length) {
|
||
|
|
const child = this.data.renderList[index];
|
||
|
|
if (!child || !child.render || child.render.call(null, (Date.now() - child.timestamp) / child.duration)) {
|
||
|
|
// 结束了,删除该动画
|
||
|
|
this.setData({
|
||
|
|
renderList: [...this.data.renderList].filter((_item, fIndex) => fIndex != index),
|
||
|
|
});
|
||
|
|
length--;
|
||
|
|
} else {
|
||
|
|
// continue
|
||
|
|
index++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
start() {
|
||
|
|
const render = this.createRender();
|
||
|
|
const duration = getRandom(1500, 3000);
|
||
|
|
this.setData({
|
||
|
|
renderList: [
|
||
|
|
...this.data.renderList,
|
||
|
|
{
|
||
|
|
render,
|
||
|
|
duration,
|
||
|
|
timestamp: Date.now(),
|
||
|
|
},
|
||
|
|
],
|
||
|
|
});
|
||
|
|
|
||
|
|
if (!this.data.scanning) {
|
||
|
|
this.setData({
|
||
|
|
scanning: true,
|
||
|
|
});
|
||
|
|
|
||
|
|
this.requestFrame(this.scan.bind(this));
|
||
|
|
// this.scan.bind(this)();
|
||
|
|
}
|
||
|
|
return this;
|
||
|
|
},
|
||
|
|
requestFrame(cb) {
|
||
|
|
return (
|
||
|
|
this.data.context.requestAnimationFrame ||
|
||
|
|
(function (callback) {
|
||
|
|
setTimeout(callback, 1000 / 60);
|
||
|
|
})(cb)
|
||
|
|
);
|
||
|
|
},
|
||
|
|
},
|
||
|
|
});
|