npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

hcanvas

v1.0.0

Published

简单来讲hcanvas就是在canvas上实现了一套浏览器渲染引擎,可以将html css显示到canvas上,并且提供了dom操作、动画、注册事件等功能。 hcanvas的api及操作方式都是前端开发者最熟悉的html、css、事件、dom操作、动画等,对于前端开发者来说学习成本几乎为0。 hcanvas非常的轻量,没有任何npm依赖,所有逻辑都是在框架中实现。 ## 应用场景 如果你的项目有丰富动画互动效果,为保证前端性能需要在canvas上实现时 如果想在canvas上展示复杂的布局,但

Readme

介绍

hcanvas是什么?

简单来讲hcanvas就是在canvas上实现了一套浏览器渲染引擎,可以将html css显示到canvas上,并且提供了dom操作、动画、注册事件等功能。
hcanvas的api及操作方式都是前端开发者最熟悉的html、css、事件、dom操作、动画等,对于前端开发者来说学习成本几乎为0。
hcanvas非常的轻量,没有任何npm依赖,所有逻辑都是在框架中实现。

应用场景

如果你的项目有丰富动画互动效果,为保证前端性能需要在canvas上实现时
如果想在canvas上展示复杂的布局,但苦于操作canvas复杂的api时
如果你时间紧急,挑选canvas框架发现其他框架学习成本较高时
如果你项目的体量没有达到需要动用游戏引擎那么厚重的框架时
hcanvas是个很好的选择。

安装

hcanvas使用umd规范打包,可以用多种方式引用。

npm方式

npm install hcanvas --save
import hcanvas from 'hcanvas';
let hc = new hcanvas({
    //options
});

script引入

<script src="./dist/hcanvas.js"></script>
<script>
let hc = new hcanvas({
    //options
});
</script>

其他规范

CommonJs、CMD、AMD都可以

使用

准备好一个canvas元素,css定义好尺寸

<canvas id="canvasDom"></canvas>

创建hcanvas实例

let classes = {
    divBox: {
        width: 500,
        height: 500,
        backgroundColor: '#0000ff',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center'
    },
    div: {
        width: 100,
        height: 100,
    },
    span: {
        color: '#ffffff',
        width: 100,
        height: 100,
        fontSize: 20,
        lineHeight: 100,
        textAlign: 'center'
    },
};
let hc = new hcanvas({
    canvasDom: document.getElementById('canvasDom'),
    initElement: `
        <root>
            <div class="divBox">
                <div id="divDom" class="div" style="background-color: #ff0000">
                    <span class="span">Aaa</span>
                </div>
            </div>
        </root>
        `,
    classes: classes
});

就这么简单。

classes为一个class样式集合对象,子对象为一个类,属性就是css属性,如遇到带有-的属性,就转为驼峰的形式,如果嫌这样写着麻烦,可以自行实现loader转换。

样式也可以写在标签内,标签内样式不用转换-,按照css规则写即可。

initElement为初始化的dom元素,根元素用root标签。

initElement可以像例子中这样使用字符串,也可以使用hcanvas dom对象(此dom对象指的是hcanvas内部dom对象,非html的dom,下文有介绍)。

如嫌initElement写着麻烦并且没有语法高亮,可将html放到编辑器可识别的文件里,然后自行实现loader转换。

hcanvas没有实现所有html标签,虽然只实现了几个,但绝对够用。本例中用到了div和span,后面还有其他标签介绍。

效果如下:

布局

hcanvas采用flex布局,未实现其他布局方式,且display属性默认为flex,可以不指定。

可以不使用布局,不使用的方式就是在样式中指定x、y属性,有了x、y属性就会跳出布局。x、y相对于父元素左上角。

flex布局的所有内容均已实现,请放心使用。

示例

let classes2 = {
    divBox: {
        width: 500,
        height: 500,
        backgroundColor: '#0000ff',
        alignItems: 'center',
        justifyContent: 'center',
        flexDirection: 'column'
    },
    div1: {
        backgroundColor: '#ff0000',
        width: 100,
        height: 100,
    },
    div2: {
        backgroundColor: '#00ff00',
        width: 100,
        height: 100,
    },
    div3: {
        backgroundImage: 'http://xxx.xxx.com/xxx.png',//图片地址
        width: 100,
        height: 100,
        marginTop: 10
    },
    divNoLayout: {
        width: 100,
        height: 100,
        x: 10,
        y: 10,
        backgroundColor: '#ffff00',
    }
};
<root>
    <div class="divBox">
        <div class="div1"></div>
        <div class="div2"></div>
        <div class="div3"></div>
        <div class="divNoLayout"></div>
    </div>
</root>

效果如下,黄色div使用了x、y脱离了布局。div3使用了背景图片和margin

dom操作

api操作

hcanvas实现了一系列dom操作api,推荐使用api操作

let hc = new hcanvas({
    canvasDom: document.getElementById('canvasDom'),
    initElement: `
        <root>
            <div id="divBox" class="divBox" style="width:500">
                <div class="div1"></div>
                <div class="div2"></div>
                <div id="div3" class="div3"></div>
            </div>
        </root>
    `,
    classes: classes
});
let divBoxDom = hc.getElementById('divBox');//获取元素
let div3Dom = hc.getElementById('div3');
divBoxDom.append(`<div class="div2"></div>`);//添加元素
div3Dom.addClass('div4');//添加类
div3Dom.removeClass('div4');//删除类
div3Dom.remove();//删除元素

是不是很眼熟?没错getElementById参考了浏览器api,append、remove、addClass、removeClass参考了jquery的dom操作api。

hcanvas dom操作

如果将上例的divBoxDom输出一下,你会看到他是这样的。

{
    type: 'div',
    id: 'divBox',
    class: 'divBox',
    style: {
        width: 500
    },
    children:[
        {
            type: 'div',
            class: 'div1',
            //很多属性...
        },
        //很多属性...
    ],
    //很多属性...
}

这就是之前提到的hcanvas dom对象,它就是一个js对象,你可以用你所知道的任何js方法操作它。你可以改样式,改类,改子节点,任何修改都会更新到canvas上。

如果你愿意的话,你可以写一个转换插件,将vue或react的虚拟dom转换为hcanvas dom,那么理论上hcanvas就可以渲染vue和react了。

元素及样式支持

<root></root><!--根元素,你可以把它当成html的body-->

<div></div><!--div,你懂的-->

<span>文本</span><!--用于显示文本标签,目前文本只能放到span里,与html不同,这里的span是块级-->

<img src="http://xxx.xxx.xxx/xxx.png"></img><!--图片,与html的img差不多,不同是这里的img可以拥有子元素,可以当容器使用-->

<plg pointArr="[[0,0],[100,0],[100,100],[0,100]]"></plg><!--多边形,pointArr为二维数组,代表多边形每个点的坐标,此坐标相对于plg自身基点origin-->

<fra duration="500" keyframe='[{"percent":0,"src":"图片地址"},{"percent":50,"src":"图片地址"},{"percent":100,"src":"图片地址"}]'></fra><!--帧动画,duration为帧动画执行时间,单位毫秒。keyframe为数组,里面的元素是关键帧,percent为关键帧百分比。帧动画需要配合js方法使用,下面有介绍。-->

样式支持:
flex(flex所有相关属性都支持,不一一列举了)、width、height、margin(left top right bottom)、padding(left top right bottom)、background-color、background-image(使用方法与css有区别,直接写图片地址)、opacity、color、x、y、white-space、font-size、font-family、font-weight、line-height、text-align、rotate(不同于css的rotate,这里不用放到transform,直接这样写rotate:45)、origin(同rotate,直接写origin:50% 50%)、scale(同rotate,直接写scale:0.5 0.5)

事件

hcanvas暂时采用dom0级事件,支持阻止冒泡,扩展了事件对象

let hc = new hcanvas({
    canvasDom: document.getElementById('canvasDom'),
    initElement: `
        <root>
            <div class="divBox">
                <div id="div1" class="div1">
                    <div id="div2" class="div2"></div>
                </div>
            </div>
        </root>
                `,
    classes: classes
});
let domDiv1 = hc.getElementById('div1');
domDiv1.onclick = function () {
    console.log('click div1');
};
let domDiv2 = hc.getElementById('div2');
domDiv2.onclick = function (e) {
    console.log('click div2');
    console.log(e);
    e.stopPropagation();
};

上例中e.stopPropagation();有阻止冒泡的作用,点击div2,只输出div2。如果去掉stopPropagation,则会冒泡,输出div2 div1
上例中的事件对象如下

{
    target:{},//触发事件的dom
    clientX: 10,//相对于canvas的坐标
    clientY: 10,//相对于canvas的坐标
    offsetX: 10,//相对于target的坐标
    offsetY: 10,//相对于target的坐标
}

多边形的事件触发已经过精准的计算,请放心使用。

动画

hcanvas实现了两种动画,一种是动画api(位移、形变、旋转、缩放等改变样式的动画),一种是帧动画。

动画api

let hc = new hcanvas({
    canvasDom: document.getElementById('canvasDom'),
    initElement: `
        <root>
            <div class="divBox">
                <div id="div" class="div">
                    <span class="span">Aaa</span>
                </div>
            </div>
        </root>
            `,
    classes: classes
});
let domDiv = hc.getElementById('div');
domDiv.onclick = function () {
    hc.animate(
        domDiv, //触发元素
        {//变化的样式
            x: 150,
            rotate: 120,
        }, 
        1000, //执行时间
        [.3, 1.33, .49, 1.56],//贝塞尔曲线
        0,//延迟时间
        () => {//回调函数
            console.log('end');
        }
    );
};

帧动画

let hc = new hcanvas({
    canvasDom: document.getElementById('canvasDom'),
    initElement: `
        <root>
            <div class="divBox">
                <fra id="fra" duration="1000"
                    keyframe='[
                        {"percent":0,"src":"图片地址"},
                        ...
                        {"percent":50,"src":"图片地址"},
                        ...
                        {"percent":100,"src":"图片地址"}
                    ]'>
                </fra>
            </div>
        </root>
            `,
    classes: classes
});
let domFra = hc.getElementById('fra');
//帧动画执行时间在元素的duration属性里
domFra.onclick = function () {
    domFra.play(
        [.05, .89, .1, .95],//贝塞尔曲线
        100, //延时时间
        () => {//回调函数
            console.log('end');
        }
    );
};

上面两个动画的例子放到一起,效果如下

移动端适配

适配移动端非常简单,只需在配置里加上rem:true即可

let classes = {
    divBox: {
        width: 750,
        height: 750,
        backgroundColor: '#0000ff',
    },
    div: {
        width: 375,
        height: 100,
        backgroundColor: '#ff0000',
    },
};
let hc = new hcanvas({
    rem: true,
    canvasDom: document.getElementById('canvasDom'),
    initElement: `
        <root>
            <div class="divBox">
                <div class="div">
                </div>
            </div>
        </root>
            `,
    classes: classes
});

效果如下图,以设计稿为750位基准,红色div宽度375正好占据一半

性能优化

hcanvas做了如下性能优化

响应式渲染:hcanvas在内部监听dom元素变化,只有dom元素发生改变时才会触发渲染。

动画队列:当某个元素的动画需要执行多套时(比如多组变化执行时间不一样),或者同时有多个元素在动,请放心的执行多个动画api,hcanvas启用了动画队列机制,无论多少个动画,hcanvas都只启用一个定时器。