摘要:你们说,能不能把这个贪吃蛇游戏插入到编辑中呢?

本文分享自华为云社区《整个贪吃蛇到编辑器里玩吧》,原文作者:DevUI。

能不能把这个贪吃蛇游戏插入到编辑中呢?

按照以下四个步骤来就行:

  • 第一步:自定义工具栏按钮
  • 第二步:自定义Blot内容
  • 第三步:在Quill注册自定义Blot
  • 第四步:调用Quill的API插入自定义内容

第一步:自定义工具栏按钮

这个非常简单:

const TOOLBAR_CONFIG = [[{ header: ['1', '2', '3', false] }],['bold', 'italic', 'underline', 'link'],[{ list: 'ordered' }, { list: 'bullet' }],['clean'],['card', 'divider', 'emoji', 'file', 'tag'],['dragon', 'snake'], // 新增的
];

自定义工具栏按钮图标:

const snakeIcon = `<svg>...</svg>`;
const icons = Quill.import('ui/icons');
icons.snake = snakeIcon;

增加工具栏按钮事件:

const quill = new Quill('#editor', {theme: 'snow',modules: {toolbar: {container: TOOLBAR_CONFIG,handlers: {...// 增加一个空的事件snake(value): void {console.log('snake~~');},},}},
});

第二步:自定义Blot内容 SnakeBlot

不再啰嗦,参考之前的文章直接写就好:

《如何将龙插入到编辑器中? 》

《Quill富文本编辑器的实践》

snake.ts

import Quill from 'quill';
import GreedySnake from '../../shared/greedy-snake';const BlockEmbed = Quill.import('blots/block/embed');class SnakeBlot extends BlockEmbed {static blotName = 'snake';static tagName = 'canvas';static create(value): any {const node = super.create(value);const { id, width, height } = value;node.setAttribute('id', id || SnakeBlot.blotName);if (width !== undefined) {node.setAttribute('width', width);}if (height !== undefined) {node.setAttribute('height', height);}// 绘制贪吃蛇游戏的代码参考对半同学的文章:https://juejin.cn/post/6959789039566192654new GreedySnake(node).start();return node;}
}export default SnakeBlot;

绘制贪吃蛇

由于对半同学花一个小时写出来的代码实在非常优雅,忍不住将其代码贴出来了(侵删),文章源码来源于对半同学的文章:

canvas 300行代码实现一个贪吃蛇

greedy-snake.ts

// 大小为64 * 40
export default class GreedySnake {canvas;ctx;maxX;maxY;itemWidth;direction;speed;isStop;isOver;isStart;score;timer;j;canChange;grid;snake;food;// mask;// scoreDom;constructor(container) {this.canvas = typeof container === 'string' ? document.querySelector(container) : container;this.canvas.setAttribute('width', 640);this.canvas.setAttribute('height', 400);this.canvas.setAttribute('style', 'border: solid 2px #ddd');this.ctx = this.canvas.getContext('2d');this.maxX = 64;          // 最大行this.maxY = 40;          // 最大列this.itemWidth = 10;     // 每个点的大小this.direction = 'right'; // up down right left 方向this.speed = 150;        // ms 速度this.isStop = false;     // 是否暂停this.isOver = false;     // 是否结束this.isStart = false;    // 是否开始this.score = 0;          // 分数this.timer = null;       // 移动定时器this.j = 1;this.canChange = true;this.grid = new Array();// this.scoreDom = document.querySelector('#score');// this.mask = document.querySelector('#mask');for (let i = 0; i < this.maxX; i++) {for (let j = 0; j < this.maxY; j++) {this.grid.push([i, j]);}}this.drawGridLine();this.getDirection();document.addEventListener('keydown', (event) => {if (event.keyCode === 13) {if (!this.isStart) return;this.start();}});}// 开始start(): void {if (this.timer) {clearTimeout(this.timer);}if (!this.isStart) {this.isStart = true;}this.score = 0;this.speed = 150;this.isStop = false;this.isOver = false;this.direction = 'right';this.createSnake();this.createFood();this.draw();this.move();// this.mask.style.display = 'none';}// 创建蛇主体createSnake(): void {this.snake = [[4, 25],[3, 25],[2, 25],[1, 25],[0, 25]];}// 移动move(): void {if (this.isStop) {return;}let [x, y] = this.snake[0];switch (this.direction) {case 'left':x--;break;case 'right':x++;break;case 'up':y--;break;case 'down':y++;break;}// 如果下一步不是食物的位置if (x !== this.food[0] || y !== this.food[1]) {this.snake.pop();} else {this.createFood();}if (this.over([x, y])) {this.isOver = true;// this.mask.style.display = 'block';// this.mask.innerHTML = '结束';return;}if (this.completed()) {// this.mask.style.display = 'block';// this.mask.innerHTML = '恭喜您,游戏通关';return;}this.snake.unshift([x, y]);this.draw();this.canChange = true;this.timer = setTimeout(() => this.move(), this.speed);}// 暂停游戏stop(): void {if (this.isOver) {return;}this.isStop = true;// this.mask.style.display = 'block';// this.mask.innerHTML = '暂停';}// 继续游戏continue(): void {if (this.isOver) {return;}this.isStop = false;this.move();// this.mask.style.display = 'none';}getDirection(): void {// 上38 下40 左37 右39 不能往相反的方向走document.onkeydown = (e) => {// 在贪吃蛇移动的间隔内不能连续改变两次方向if (!this.canChange) {return;}switch (e.keyCode) {case 37:if (this.direction !== 'right') {this.direction = 'left';this.canChange = false;}break;case 38:if (this.direction !== 'down') {this.direction = 'up';this.canChange = false;}break;case 39:if (this.direction !== 'left') {this.direction = 'right';this.canChange = false;}break;case 40:if (this.direction !== 'up') {this.direction = 'down';this.canChange = false;}break;case 32:// 空格暂停与继续if (!this.isStop) {this.stop();} else {this.continue();}break;}};}createPos(): any {// tslint:disable-next-line: no-bitwiseconst [x, y] = this.grid[(Math.random() * this.grid.length) | 0];for (const item of this.snake) {if (item[0] === x && item[1] === y) {return this.createPos();}}// for (let i = 0; i < this.snake.length; i++) {//   if (this.snake[i][0] === x && this.snake[i][1] === y) {//     return this.createPos();//   }// }return [x, y];}// 生成食物createFood(): void {this.food = this.createPos();// 更新分数// this.scoreDom.innerHTML = 'Score: ' + this.score++;if (this.speed > 50) {this.speed--;}}// 结束over([x, y]): boolean {if (x < 0 || x >= this.maxX || y < 0 || y >= this.maxY) {return true;}if (this.snake.some(v => v[0] === x && v[1] === y)) {return true;}}// 完成completed(): boolean {if (this.snake.length === this.maxX * this.maxY) {return true;}}// 网格线drawGridLine(): void {for (let i = 1; i < this.maxY; i++) {this.ctx.moveTo(0, i * this.itemWidth);this.ctx.lineTo(this.canvas.width, i * this.itemWidth);}for (let i = 1; i < this.maxX; i++) {this.ctx.moveTo(i * this.itemWidth, 0);this.ctx.lineTo(i * this.itemWidth, this.canvas.height);}this.ctx.lineWidth = 1;this.ctx.strokeStyle = '#ddd';this.ctx.stroke();}// 绘制draw(): void {// 清空画布this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);this.drawGridLine();this.ctx.fillStyle = '#000';this.ctx.fillRect(this.food[0] * this.itemWidth + this.j,this.food[1] * this.itemWidth + this.j,this.itemWidth - this.j * 2,this.itemWidth - + this.j * 2);// tslint:disable-next-line: no-bitwisethis.j ^= 1;this.ctx.fillStyle = 'green';this.ctx.fillRect(this.snake[0][0] * this.itemWidth + 0.5,this.snake[0][1] * this.itemWidth + 0.5,this.itemWidth - 1,this.itemWidth - 1);this.ctx.fillStyle = 'red';for (let i = 1; i < this.snake.length; i++) {this.ctx.fillRect(this.snake[i][0] * this.itemWidth + 0.5,this.snake[i][1] * this.itemWidth + 0.5,this.itemWidth - 1,this.itemWidth - 1);}}
}

第三步:在Quill注册自定义Blot

有了 SnakeBlot,还需要将其注册到 Quill 中才能使用:

import SnakeBlot from './formats/snake';
Quill.register('formats/snake', SnakeBlot);

第四步:调用Quill的API插入自定义内容

调用完API就可以玩贪吃蛇游戏啦,开心到飞起!

const quill = new Quill('#editor', {theme: 'snow',modules: {toolbar: {container: TOOLBAR_CONFIG,handlers: {...snake(value): void {console.log('snake~~');const index = this.quill.getSelection().index;// 插入自定义内容this.quill.insertEmbed(index, 'snake', {id: 'canvas-snake',});},},}},
});

效果图:

永远保持童心,保持对世界的好奇,你就是上帝带给这个世界最好的礼物。

点击关注,第一时间了解华为云新鲜技术~

我的编辑器能玩贪吃蛇,一起玩不?相关推荐

  1. 【python教程入门学习】Python实现自动玩贪吃蛇程序

    这篇文章主要介绍了通过Python实现的简易的自动玩贪吃蛇游戏的小程序,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学一学 实现效果 先看看效果 这比我手动的快多了,而且是单机的,自动玩没惹 ...

  2. 利用51单片机+hc595芯片配合在led点阵上玩贪吃蛇 第一篇“显示贪吃蛇”

    利用51单片机+hc595芯片配合在led点阵上玩贪吃蛇 第一篇"显示贪吃蛇" 完整的项目链接: https://github.com/linxinloningg/51_chip_ ...

  3. 利用51单片机+hc595芯片配合在led点阵上玩贪吃蛇 第二篇“自动运行函数”

    利用51单片机+hc595芯片配合在led点阵上玩贪吃蛇 第二篇"自动运行函数" 完整的项目链接: https://github.com/linxinloningg/51_chip ...

  4. C语言:如何在cmd命令窗口上玩贪吃蛇游戏

    最近在重新学习C语言知识,还别说,在这个过程中,我还真的学到了过去很多没有学习到C语言知识,于是就做了这个游戏–贪吃蛇. 运行结果如下: C语言:如何在cmd命令窗口上玩贪吃蛇游戏 文章目录 1. 实 ...

  5. 训练AI玩贪吃蛇(强化学习与Q-learning)

    欢迎加入我们卧虎藏龙的python讨论qq群:729683466 ●导 语 ● AI近些年发展很火 不但可以下围棋 还可以玩各种各样的游戏 国外有人构建AI模型 然后训练出了非常厉害的拳击手 相信有一 ...

  6. 正确的「记事本」打开方式:能渲染3D图像,还能玩贪吃蛇

    金磊 发自 凹非寺 量子位 报道 | 公众号 QbitAI 渲染3D图像,一个「记事本」就够了. 最近,GitHub上一名叫"Kyle Halladay"的小哥,便上传了这样一个项 ...

  7. matlab的开方算法_正确的「记事本」打开方式:能渲染3D图像,还能玩贪吃蛇

    金磊 发自 凹非寺 量子位 报道 | 公众号 QbitAI 渲染3D图像,一个「记事本」就够了. 最近,GitHub上一名叫"Kyle Halladay"的小哥,便上传了这样一个项 ...

  8. 耗时两年,19岁小伙采用230片纯74逻辑芯片搭建出32位Risc-V处理器!可玩贪吃蛇...

    来源:机器之心编译   编辑:杜伟 昨天发了一篇关于纯手工制作CPU的文章,看来大家都十分感兴趣: B站焊武帝爆火出圈:纯手工拼晶体管自制CPU,耗时半年,可跑程序! 如果你想自己DIY CPU,第一 ...

  9. 耗时两年,19岁小伙采用230片纯74逻辑芯片搭建出32位处理器!可玩贪吃蛇

    从设计 CPU.制作原型机.最终成品到软件编程,19 岁极客小伙用了整整两年的时间. RISC-V 是一个基于精简指令集(RISC)原则的开源指令集架构(ISA),它是对应开源软件运动的一种「开源硬件 ...

最新文章

  1. 调试U-Boot笔记(一)
  2. TCP协议——流量控制和拥塞控制
  3. Android Coding利器之掌握小技巧,助你Coding更上一层楼~
  4. 如何使用Wondershare Recoverit for Mac从崩溃的 Mac 恢复数据?
  5. 是时候学习生成对抗网络了,李宏毅老师GAN视频教程下载
  6. 通达信里的统计函数及区块背景函数
  7. 模拟利器Mockito
  8. 实验1-5 输出菱形图案 (5 分)
  9. 系统损坏 mysql_mysql数据库损坏修复方法(适用window、Linux系统vps云主机)
  10. 华为user-bind不允许使用dhcp功能的情况下的使用
  11. 详解BSCI实验一、配置EIGRP 验证,汇总
  12. STM8S103K3和STM8S105K4原理图
  13. 【Proteus仿真】PCF8591 AD电压采集8X8点阵显示
  14. 手把手教你Excel数据处理!
  15. echarts 地图自定义图标_echarts 使用 百度地图 加入自定义图标标记
  16. jquery 立体走马灯_CSS3超酷3D文字跑马灯特效
  17. 基于android的快递寄件平台
  18. Mysql Mac 免安装教程
  19. android 爬虫获取邮箱,python爬虫源码学习:爬虫smtp邮件实时推送(2)
  20. storm mysql trident_Apache Storm 官方文档 —— Trident 教程

热门文章

  1. Bootstrap3 地址元素样式
  2. JSON 语法之 JSON 文件
  3. python数据序列题库_Python题库系列分享一(17道)
  4. img pdf 展示_pdf.js实现图片在线预览
  5. antdesign 柱状图_以Ant Design为例:看B端设计的基本套路
  6. kaggle:PUBG Finish Placement Prediction
  7. CJOJ 【DP合集】最长上升序列2 — LIS2
  8. django的form常用字段和参数
  9. beeline连接hive
  10. HDU 1162 Eddy's picture (最小生成树)(java版)