打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
在你的 VSCode 里深夜放烟火

来源丨经授权转自 神光的编程秘籍

作者丨神说要有光zxg

我从没有见过极光出现的村落

也没有见过有人 在深夜放烟火

见过有人在 vscode 里深夜放烟火么?

今天我们就一起来放一下:


首先,vscode 是基于 electron 实现的,也就是界面都是网页写的。

而且它有一个 decoration 的 api,可以给 editor 的文本加样式:

参数有 before、after 也就是前后加一个伪元素,还有 border、backgound 等样式。

是不是就和写 css 一样?

因为它本来就是 css。

基于这个 api,我们就可以给某段文本加一段样式。

这就是 vscode 里放烟花的原理。

下面我们来写一下:

全局安装 vscode 插件脚手架:

npm install -g yo generator-code

然后创建 vscode 插件项目:

yo code

点击调试,会出现新的 vscode 窗口,然后输入 hello world 命令,右下角有 hello world 弹窗:


这就说明插件跑成功了。

然后我们开始写具体的逻辑:

在 src/extension.ts 里注册 fireworks 命令:

import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext{

 const fireworksCommand = vscode.commands.registerCommand('fireworks', () => {
  vscode.window.showInformationMessage('光光光');
 });

 context.subscriptions.push(fireworksCommand);
}

export function deactivate({}

然后在 package.json 里声明这个命令:

跑起来就是这样的:

然后用下 decaration 的 api:

import * as vscode from 'vscode';

export function activate(context: vscode.ExtensionContext{

 const fireworksCommand = vscode.commands.registerCommand('fireworks', () => {
  const editor = vscode.window.activeTextEditor;

  if(editor) {
   const decoration = vscode.window.createTextEditorDecorationType({
    before: {
     contentText'光光光',
     backgroundColor'red'
    },
    border'10px solid green',
    after: {
     contentText'东东东',
     backgroundColor'blue'
    }
   });

   const position1 = new vscode.Position(12);
   const position2 = new vscode.Position(14);

   const range = new vscode.Range(position1, position2);

   editor.setDecorations(decoration, [range]);
  }
 
 });

 context.subscriptions.push(fireworksCommand);
}

export function deactivate({}

我们用 vscode.window.activeTextEditor 拿到当前的 editor。

创建 decoration 对象,指定 border 还有 before、after 伪元素的样式。

指定开始和结束的 position,然后给这段 range 添加 decoration。

测试下:


可以看到,执行命令后,第 1 行第 2 到 4 列(vscode 里的行列号是从 0 开始的)的文本被加上了边框了,并且前后加了伪元素。

选中的文本复制之后却没有带上前后伪元素。

这个就是伪元素本身的特性:

比较有意思的一点是样式的值其实可以写任意多个样式:

也就是说,在 vscode 的 editor 里能实现各种用 css 能实现的效果。

那放烟花怎么实现呢?

其实就是用 background-image 加载一个 gif 就好了。

这里我们用内嵌 base64 图片的方式:

创建 src/gifs.ts:

const gifData1= 'xxx';

consg gifData2= 'xxx';

export {
    gifData1,
    gifData2

内容比较多,可以从 github 复制:https://github.com/QuarkGluonPlasma/vscode-night-fireworks/blob/main/src/gifs.ts

然后设置 background-image:

让元素相对定位,伪元素绝对定位,然后设置宽高、background-image。

let cssStr = `position:absolute;width:100px;height:100px;`
cssStr += `background-image: url(${gifData1});`;
cssStr += 'background-size: contain;';
cssStr+= 'background-repeat: no-repeat;'

const decoration = vscode.window.createTextEditorDecorationType({
        before: {
                contentText'',
                textDecoration`none;${cssStr};`
        },
        textDecoration'none;position:relative;'
});

效果是这样的:

这样就可以在 vscode 里放烟花了。

当然,现在的烟花位置是固定的,我们可以多加几个,并且位置随机一点:

拿到 editor 的文本,按照换行符分割下:

打个断点,断住以后是这样的:

我们根据这个来计算出在哪里加烟花就好了。

可以随机列、随机行放一个。

封装这样一个方法:

function randomRange(start: number, end: number{
    return Math.ceil(start + Math.random() * (end - start));
}

随机产生从 xxx 到 yyy 的值。

然后每 10 到 20 行,在那行的随机位置,放一个烟花的装饰,随机从两个 gif 里取一个:

import * as vscode from 'vscode';
import { gifData1, gifData2 } from './gifs';

function randomRange(start: number, end: number{
 return Math.ceil(start + Math.random() * (end - start));
}

export function activate(context: vscode.ExtensionContext{

 const fireworksCommand = vscode.commands.registerCommand('fireworks', () => {
  const editor = vscode.window.activeTextEditor;

  if(editor) {
   let cssStr = `position:absolute;width:150px;height:100px;`
   cssStr += 'background-size: contain;';
   cssStr+= 'background-repeat: no-repeat;'

   const text = editor.document.getText();
   const lines = text.split('\n');


   for(let i = 0; i < lines.length; i+= randomRange(1020)) {
    const line = lines[i];

    cssStr += `background-image: url(${Math.random() > 0.5 ? gifData1 : gifData2});`;

    const j = Math.random() * lines[i].length;

    const position1 = new vscode.Position(i, j);
    const position2 = new vscode.Position(i, j + 1);
  
    const range = new vscode.Range(position1, position2);

    const decoration = vscode.window.createTextEditorDecorationType({
     before: {
      contentText'',
      textDecoration`none;${cssStr};`
     },
     textDecoration'none;position:relative;'
    });
 
    editor.setDecorations(decoration, [range]);

   }
  }
 
 });

 context.subscriptions.push(fireworksCommand);
}

export function deactivate({}

效果是这样的:


放烟火之后如何去掉呢?

其实 decoration 有个 deispose 方法是用来做这个的:

所以我们把 decoration 收集起来,注册个新 command 用来去掉烟花,并且在每次放烟花前把之前的去掉:

import * as vscode from 'vscode';
import { gifData1, gifData2 } from './gifs';

function randomRange(start: number, end: number{
 return Math.ceil(start + Math.random() * (end - start));
}

let decorations: vscode.TextEditorDecorationType[] = [];

export function activate(context: vscode.ExtensionContext{
 function disposeAllDecorations({
  decorations.forEach(item => {
   item.dispose();
  });
  decorations = [];
 }
 const stopFireworksCommand = vscode.commands.registerCommand('stop-fireworks', disposeAllDecorations);

 context.subscriptions.push(stopFireworksCommand);

 const fireworksCommand = vscode.commands.registerCommand('fireworks', () => {
  const editor = vscode.window.activeTextEditor;

  if(editor) {
   let cssStr = `position:absolute;width:150px;height:100px;`
   cssStr += 'background-size: contain;';
   cssStr+= 'background-repeat: no-repeat;'

   const text = editor.document.getText();
   const lines = text.split('\n');

   disposeAllDecorations();
   for(let i = 0; i < lines.length; i+= randomRange(1020)) {
    const line = lines[i];

    cssStr += `background-image: url(${Math.random() > 0.5 ? gifData1 : gifData2});`;

    const j = Math.random() * lines[i].length;

    const position1 = new vscode.Position(i, j);
    const position2 = new vscode.Position(i, j + 1);
  
    const range = new vscode.Range(position1, position2);

    const decoration = vscode.window.createTextEditorDecorationType({
     before: {
      contentText'',
      textDecoration`none;${cssStr};`
     },
     textDecoration'none;position:relative;'
    });
 
    editor.setDecorations(decoration, [range]);

    decorations.push(decoration);
   }
  }
 
 });

 context.subscriptions.push(fireworksCommand);
}

当然,在 package.json 里也得注册下这个 command:

测试下:


确实去掉了。

然后我们加个快捷键:

'keybindings': [
  {
    'command''fireworks',
    'key''ctrl+y',
    'mac''cmd+y'
  },
  {
    'command''stop-fireworks',
    'key''ctrl+shift+y',
    'mac''cmd+shift+y'
  }
]

在 windows 下是 ctrl + y 在 mac 下是 cmd + y。

测试下:

这样就可以方便的放烟花和停止了。

代码上传了 github:https://github.com/QuarkGluonPlasma/vscode-night-fireworks

总结

我们实现了在 vsocde 里放烟花的效果。

vscode 是基于 electron 实现的,看到的界面都是网页,并且 vscode 提供了 decoration 的 api 可以给一段文本加装饰。

这个装饰可以写任意的 css。

我们注册了 fireworks 和 stop-fireworks 两个命令。

在 fireworks 的时候拿到文本,给随机行列加上一个装饰,也就是通过 before 伪元素加上 background-image 设置一个 gif。

然后 stop-fireworks 的时候调用 dispose 去掉装饰。

这样,深夜里就可以在 vscode 里自己放烟火了。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
网易前端2020笔试编程题--1.序列转换
如何配置VSCode,才会好用到飞起~【1】
CSS Sprite的应用
快过年了,用五种不同的JS特效带你看烟花(包邮送元宇宙图书)
delphi快速获取网页源码方法
c# 如何在winform中模拟鼠标点击事件
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服