下载地址:https://www.pan38.com/share.php?code=JCnzE 提取密码:7789
元素渲染和交互功能。主类DouyinCardGenerator提供了添加卡片、渲染元素、切换卡片和导出图片等功能。代码结构清晰,包含初始化、事件绑定、渲染逻辑等多个模块,可以轻松扩展更多卡片样式和交互效果。
class DouyinCardGenerator {
constructor(options = {}) {
this.width = options.width || 375;
this.height = options.height || 667;
this.backgroundColor = options.backgroundColor || '#ffffff';
this.cards = [];
this.currentCardIndex = 0;
this.initDOM();
this.bindEvents();
}
initDOM() {
this.container = document.createElement('div');
this.container.className = 'douyin-card-container';
Object.assign(this.container.style, {
width: ${this.width}px
,
height: ${this.height}px
,
backgroundColor: this.backgroundColor,
position: 'relative',
overflow: 'hidden'
});
this.canvas = document.createElement('canvas');
this.canvas.width = this.width;
this.canvas.height = this.height;
this.ctx = this.canvas.getContext('2d');
this.container.appendChild(this.canvas);
document.body.appendChild(this.container);
}
bindEvents() {
this.container.addEventListener('click', this.handleClick.bind(this));
window.addEventListener('resize', this.handleResize.bind(this));
}
handleClick(e) {
const x = e.clientX - this.container.offsetLeft;
const y = e.clientY - this.container.offsetTop;
if (x > this.width - 100 && y < 100) {
this.nextCard();
} else if (x < 100 && y < 100) {
this.prevCard();
}
}
handleResize() {
const scale = Math.min(
window.innerWidth / this.width,
window.innerHeight / this.height
);
Object.assign(this.container.style, {
transform: scale(${scale})
,
transformOrigin: 'top left'
});
}
addCard(cardData) {
const card = {
id: Date.now(),
...cardData,
elements: []
};
this.cards.push(card);
this.renderCard(card);
return card.id;
}
renderCard(card) {
this.ctx.clearRect(0, 0, this.width, this.height);
// 绘制背景
if (card.backgroundImage) {
const img = new Image();
img.onload = () => {
this.ctx.drawImage(img, 0, 0, this.width, this.height);
this.renderElements(card);
};
img.src = card.backgroundImage;
} else {
this.ctx.fillStyle = card.backgroundColor || this.backgroundColor;
this.ctx.fillRect(0, 0, this.width, this.height);
this.renderElements(card);
}
}
renderElements(card) {
card.elements.forEach(element => {
switch (element.type) {
case 'text':
this.renderText(element);
break;
case 'image':
this.renderImage(element);
break;
case 'video':
this.renderVideo(element);
break;
}
});
}
renderText(element) {
this.ctx.font = ${element.fontSize || 16}px ${element.fontFamily || 'Arial'}
;
this.ctx.fillStyle = element.color || '#000000';
this.ctx.textAlign = element.align || 'left';
this.ctx.fillText(
element.text,
element.x,
element.y,
element.maxWidth || this.width
);
}
renderImage(element) {
const img = new Image();
img.onload = () => {
this.ctx.drawImage(
img,
element.x,
element.y,
element.width || img.width,
element.height || img.height
);
};
img.src = element.src;
}
renderVideo(element) {
// 视频元素需要特殊处理
const video = document.createElement('video');
video.src = element.src;
video.autoplay = true;
video.loop = true;
video.muted = true;
video.style.display = 'none';
this.container.appendChild(video);
const drawVideoFrame = () => {
if (video.readyState >= video.HAVE_CURRENT_DATA) {
this.ctx.drawImage(
video,
element.x,
element.y,
element.width || video.videoWidth,
element.height || video.videoHeight
);
}
requestAnimationFrame(drawVideoFrame);
};
video.play();
drawVideoFrame();
}
nextCard() {
if (this.currentCardIndex < this.cards.length - 1) {
this.currentCardIndex++;
this.renderCard(this.cards[this.currentCardIndex]);
}
}
prevCard() {
if (this.currentCardIndex > 0) {
this.currentCardIndex--;
this.renderCard(this.cards[this.currentCardIndex]);
}
}
exportAsImage() {
return this.canvas.toDataURL('image/png');
}
}
// 使用示例
const generator = new DouyinCardGenerator({
width: 375,
height: 667,
backgroundColor: '#f8f8f8'
});
// 添加卡片
const cardId = generator.addCard({
backgroundImage: 'https://example.com/bg.jpg',
backgroundColor: '#ffffff'
});
// 添加元素
generator.cards[0].elements.push({
type: 'text',
text: '抖音热门卡片',
x: 50,
y: 100,
fontSize: 24,
color: '#ff0050',
align: 'center'
});
generator.cards[0].elements.push({
type: 'image',
src: 'https://example.com/avatar.jpg',
x: 100,
y: 150,
width: 100,
height: 100
});