前言
随着各类视频平台的不断发展,影视剧资源占比向视频平台倾斜。除了紧凑的剧情等客观因素的存在,如何调动观众的心绪也是重要的一点,于是弹幕应运而生了。早期的弹幕只是一段可见的文字,现在则别具一格,剧情的起承转合由观众们共同鉴赏和讨论,这不仅营造了独特的观剧氛围引起共鸣,而且有助于观众自主推广,还能实时反馈观众的看法,一举多得。借助MarsCode
也可以实现一些常见的弹幕样式。
比如:
弹幕基础:输入框、发送按钮、画布
首先我们需要使用MarsCode构建一个简单的弹幕模式,在对话框中输入以下内容:
-
用JS构建一个包含输入框和发送按钮的弹幕
-
完善loop函数
-
完善屏幕、文本框和按钮模式看上去更美观
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const danmakuInput = document.getElementById('danmaku-input');
const sendBtn = document.getElementById('send-btn');
let danmakus = []; // 存储所有弹幕的数组
sendBtn.addEventListener('click', function() {
const text = danmakuInput.value;
if (text!== '') {
sendDanmaku(text);
danmakuInput.value = '';
}
});
// 横着方向
function sendDanmaku(text) {
// 将弹幕内容添加到数组中
danmakus.push({
text: text,
x: canvas.width,
y: Math.random() * canvas.height,
speed: 2,// 弹幕的速度
});
}
function loop() {
// 清除画布
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 遍历所有弹幕,绘制并更新它们的位置
danmakus.forEach(function(danmaku) {
// 字体设置
ctx.fillStyle = 'white';
ctx.font = '30px LiSu';
for (let i = 0; i < danmaku.text.length; i++) {
ctx.fillText(danmaku.text[i], danmaku.x+ i * 30, danmaku.y ); // 每个字符的 x坐标递增
}
// 更新弹幕的位置
danmaku.x -= danmaku.speed;
});
// 循环调用 loop 函数
requestAnimationFrame(loop);
}
// 启动 loop 函数
window.onload = loop;
得到一个基础的弹幕样式,如下:
屏幕内容太单调,需要添加些新内容
需要弹幕文字和图片搭配显得生动些,我所设想的是文字和图片由下至上一起移动。
此时MarsCode在数组对象中添加了新的Image对象,我们可以根据与弹幕文字的搭配程度等选择相应图片。
// 将弹幕内容添加到数组中
danmakus.push({
text: text,
x: Math.random() * canvas.width, // 随机的 x 坐标
y: canvas.height, // 初始 y 坐标为画布底部
speed: 2, // 弹幕的速度
image: new Image() // 创建一个新的 Image 对象
});
// 设置图片的 src 属性
danmakus[danmakus.length - 1].image.src = 'path/to/your/image.png'; // 替换为你的图片路径
并在loop函数中添加了图片的绘制,同时将文字绘制调整至图片绘制之后,否则图片会遮住文字。以及调转文字方向,从横向变纵向。
// 绘制图片
if (danmaku.image.complete) {
ctx.drawImage(danmaku.image, danmaku.x, danmaku.y + danmaku.text.length * 30); // 在文字下方绘制图片
}
// 绘制竖直方向的文字
for (let i = 0; i < danmaku.text.length; i++) {
ctx.fillText(danmaku.text[i], imageX, imageY + i * 30); // 每个字符的 y 坐标递增
}
现在我们来调整弹幕文字和图片的位置,让文字在图片的上下左右都居中。
此时MarsCode
调整了loop函数:在绘制文字之前,计算了文字的宽度和高度,并根据图片的宽度和高度来调整文字的位置,使其在图片中居中。
// 计算文字的宽度和高度
const textWidth = ctx.measureText(danmaku.text).width;
const textHeight = 30 * danmaku.text.length; // 假设每个字符高度为30px
// 计算文字在图片中的居中位置
const imageX = danmaku.x + (danmaku.image.width - textWidth) / 2;
const imageY = danmaku.y + (danmaku.image.height - textHeight) / 2;
当时疑惑文字宽度使用measureText
,为什么高度不用measureText
。
原来measureText
没有height的属性。原因是文本的高度在Canvas的2d上下文中相对比较复杂。
文本的高度通常由字体的设计和字号等因素决定,但不像宽度那样容易有一个固定的、与布局无关的测量方式。例如,不同的字体可能有不同的行间距、上下部留白等情况。
文字的绘制与图片的绘制在同一起点,也就是说左上角是重叠的,按理说上面的代码是可以让文字居中的,但是由于我之间调整了文字的方向,所以现在文字的宽度和高度应该交换一下。 其次文字之间有留白竖直方向文字的长度应该更长。调整之后达到预期,即:
const textWidth = 30 ;// 假设每个字符高度为30px,这个数值是根据设置的font大小来的
const textHeight =ctx.measureText(danmaku.text).width-12*danmaku.text.length ;
// 绘制竖直方向的文字坐标用imageX、imageY
for (let i = 0; i < danmaku.text.length; i++) {
ctx.fillText(danmaku.text[i], imageX, imageY + i * 30); // 每个字符的 y 坐标递增
}
至此,弹幕就全部完成了,如有需要可以自行调整角度和方向等。
关于使用MarsCode的体验
- 在不规定固定语言的情况下,
MarsCode
会优先选择最容易实现目的的语言。 - 比较适合逐句的交流,类似与他人沟通的短句交流,不适合长篇大论式交流。
- 没有开启新的对话时,会自动按照我之前问问题的逻辑,以及观察我的代码内容综合回答。
最后预祝MarsCode
蒸蒸日上,更加智能,提供更好的服务!!