sanyuelanv-turntable
Version:
优化转盘转动效果 1. 缓动加速转动, 2. 均速转动 **(在没有接收到结果的时候一直均速转动)** 3. **(接受到结果)** 缓动减速转动直到停止
184 lines (183 loc) • 7.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var getRequestAnimationFrame = function () {
var fixRequestAnimationFrame = function (callback) { window.setTimeout(callback, 1000 / 60); };
return (window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || fixRequestAnimationFrame);
};
var Turntable = /** @class */ (function () {
/**
*
* @param canvas canvas 元素
* @param imageSrc 图片链接
* @param startAngle 开始弧度
* @param readyCallback 图片加载完成会调
* @param rect canvas 的尺寸。置空则采用图片尺寸
* @param fpsDom 展示 FPS 的demo
*/
function Turntable(canvas, imageSrc, startAngle, readyCallback, rect, fpsDom) {
var _this = this;
this.devFPS = 0;
this.devLastTs = Date.now();
// 正常属性
this.lastTs = 0;
this.endTs = 0;
this.fristSecDist = 0;
this.speed = 0;
this.isStart = false;
this.endAngle = -1;
this.rotateAngle = 0;
this.rotateTime = 0;
this.startAngle = 0;
this.ready = false;
this.canvas = canvas;
this.ctx = canvas.getContext('2d');
this.image = new Image();
this.image.src = imageSrc;
this.startAngle = startAngle;
this.readyCallback = readyCallback;
this.fpsDom = fpsDom;
this.image.onload = function () { _this.load(rect); };
}
/**
* 开始转动转盘
* @param turnByRoundTime 转 1 圈所用时间(ms)
*/
Turntable.prototype.start = function (turnByRoundTime) {
if (!this.ready || this.isStart)
return;
this.reset();
this.speed = 2 * Math.PI / (turnByRoundTime / 1000);
this.isStart = true;
};
/**
* stop 并不能马上把转盘停下来,只会慢慢减速停止。但在帧数稳定的情况下,会在 1 s 内结束
* @param pos 期望转到 弧度
* @param callback 停下后的回调
*/
Turntable.prototype.stop = function (angle, callback) {
// 已经设置了减速,动画没完成之前则不能再重新设置
if (!this.ready || this.endAngle >= 0)
return;
this.callback = callback;
this.endAngle = angle;
};
/**
* 还原旋转角度
*/
Turntable.prototype.resetCtxRotate = function () {
this.ctx.restore();
this.ctx.save();
this.rotateAngle = 0;
};
Turntable.prototype.load = function (rect) {
var _this = this;
if (rect == null) {
rect = { width: 0, height: 0 };
rect.width = this.image.width;
rect.height = this.image.height;
}
// 初始化尺寸
this.canvas.width = rect.width * 2;
this.canvas.height = rect.height * 2;
this.canvas.style.width = rect.width + 'px';
this.canvas.style.height = rect.height + 'px';
var widthHalf = this.canvas.width * 0.5;
var heightHalf = this.canvas.height * 0.5;
this.translatePos = { width: widthHalf, height: heightHalf };
// 定 形变圆心
this.ctx.translate(widthHalf, heightHalf);
// 定 速度 默认:转一圈用时 (1s)
this.speed = 2 * Math.PI / 0.25;
var myRequestAnimationFrame = getRequestAnimationFrame();
var step = function () {
var now = Date.now();
var dist = _this.lastTs == null ? 0 : now - _this.lastTs;
_this.lastTs = now;
_this.render(dist);
myRequestAnimationFrame(step);
if (_this.fpsDom) {
_this.devFPS += 1;
var timeDist = now - _this.devLastTs;
if (timeDist >= 1000) {
_this.devLastTs = now;
_this.fpsDom.innerHTML = _this.devFPS > 60 ? '60' : _this.devFPS + '';
_this.devFPS = 0;
}
}
};
myRequestAnimationFrame(step);
this.ctx.rotate(this.startAngle);
this.ctx.save();
if (this.readyCallback) {
this.ready = true;
this.readyCallback();
}
};
Turntable.prototype.allStop = function () {
if (this.callback)
this.callback();
this.resetCtxRotate();
this.ctx.rotate(this.endAngle);
this.reset();
};
Turntable.prototype.reset = function () {
this.endAngle = -1;
this.endTs = 0;
this.isStart = false;
this.callback = null;
this.rotateTime = 0;
this.fristSecDist = 0;
};
Turntable.prototype.renderImage = function () {
this.ctx.clearRect(-this.translatePos.width, -this.translatePos.height, this.canvas.width, this.canvas.height);
this.ctx.fillStyle = 'rgba(255, 255, 255, 0)';
this.ctx.fillRect(-this.translatePos.width, -this.translatePos.height, this.canvas.width, this.canvas.height);
this.ctx.drawImage(this.image, 0, 0, this.image.width, this.image.height, -this.translatePos.width, -this.translatePos.height, this.canvas.width, this.canvas.height);
};
Turntable.prototype.render = function (ts) {
this.renderImage();
if (this.isStart) {
this.rotateTime += ts;
var speed = this.speed;
// 前 1 S 速度 t * t * speed = nowSpeed
if (this.rotateTime <= 1000) {
speed = this.speed * (this.rotateTime / 1000) * (this.rotateTime / 1000);
}
else {
if (this.fristSecDist == 0) {
this.fristSecDist = this.rotateAngle;
}
// 结束角度确定之后,开始减速
if (this.endAngle >= 0 && this.endTs == 0) {
this.endTs = this.rotateTime + 1000;
this.resetCtxRotate();
this.ctx.rotate(this.endAngle - this.fristSecDist);
}
if (this.endTs > 0) {
// 最后 1 S 速度
var distT = (this.endTs - this.rotateTime);
speed = this.speed * (distT / 1000) * (distT / 1000);
}
}
var angle = speed * (ts / 1000);
this.rotateAngle += angle;
if (this.isStart && this.endTs != 0) {
if (this.rotateTime >= this.endTs || this.rotateAngle >= this.fristSecDist) {
// 判断这最后一下要不要加上
if ((this.rotateAngle - angle) < this.fristSecDist) {
angle = this.fristSecDist - (this.rotateAngle - angle);
this.rotateAngle += angle;
}
else {
this.allStop();
}
}
}
if (!this.isStart)
return;
this.ctx.rotate(angle);
}
};
return Turntable;
}());
exports.Turntable = Turntable;