由canvas实现btn效果有感

栏目: Html5 · 发布时间: 5年前

内容简介:最近项目上有个工业自动化的需求,做一个按钮,有按下弹起效果,你肯定会说这不是so easy吗?是的,没错,用css,分分钟写一个,不过我们是做的拓扑图,用的canvas,因此我就想css画图也是gpu绘制,css能做的效果,我大canvas理应也能实现,于是我试着用css的实现方式做了一个canvas版的按钮效果。想想我们用css怎么做一个按钮,首先我们就能想到按钮需要有阴影,我们可以使用box-shadow,他的语法如下:首先我们定义一个btn类,先画出一个按钮的基础样式

最近项目上有个工业自动化的需求,做一个按钮,有按下弹起效果,你肯定会说这不是so easy吗?是的,没错,用css,分分钟写一个,不过我们是做的拓扑图,用的canvas,因此我就想css画图也是gpu绘制,css能做的效果,我大canvas理应也能实现,于是我试着用css的实现方式做了一个canvas版的按钮效果。

css3版的立体按钮效果

想想我们用css怎么做一个按钮,首先我们就能想到按钮需要有阴影,我们可以使用box-shadow,他的语法如下:

/* x偏移量 | y偏移量 | 阴影颜色 */ box-shadow: 60px -16px teal;
/* x偏移量 | y偏移量 | 阴影模糊半径 | 阴影颜色 */ box-shadow: 10px 5px 5px black;
/* x偏移量 | y偏移量 | 阴影模糊半径 | 阴影扩散半径 | 阴影颜色 */ box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);
/* 插页(阴影向内) | x偏移量 | y偏移量 | 阴影颜色 */ box-shadow: inset 5em 1em gold;
/* 任意数量的阴影,以逗号分隔 */ box-shadow: 3px 3px red, -1em 0 0.4em olive;
/* 全局关键字 */ box-shadow: inherit; box-shadow: initial; box-shadow: unset;

首先我们定义一个btn类,先画出一个按钮的基础样式

.btn {
    border-radius: 5px;
    padding: 15px 25px;
    font-size: 22px;
    text-decoration: none;
    margin: 20px;
    color: #fff;
    position: relative;
    display: inline-block;
}
复制代码

然后我们定义一下按钮的背景色

.blue {
    background-color: #55acee;
}
复制代码

这是我们的按钮基础样式就完成了,如下所示:

由canvas实现btn效果有感

接下来我们在来为按钮添加阴影

.btn:active {
    transform: translate(0px, 5px);
    -webkit-transform: translate(0px, 5px);
    box-shadow: 0px 1px 0px 0px;
}

.blue {
    background-color: #55acee;
    box-shadow: 0px 5px 0px 0px #3C93D5;
}
复制代码

给y方向5px的偏移,就会有阴影的效果,有点立体感觉,然后按下按钮之后我们还要去掉阴影,然后按钮的位置要向下偏移响应的5px,这样效果如下所示:

由canvas实现btn效果有感

canvas版的按钮效果

css的按钮我们已经知道了其实也就是利用box-shadow绘制阴影来实现按钮的样式,那么canvas我们怎么绘制阴影呢?翻一翻万能的mdn

shadowOffsetX = float

shadowOffsetXshadowOffsetY 用来设定阴影在 X 和 Y 轴的延伸距离,它们是不受变换矩阵所影响的。负值表示阴影会往上或左延伸,正值则表示会往下或右延伸,它们默认都为 0

shadowOffsetY = float

shadowOffsetX 和 shadowOffsetY 用来设定阴影在 X 和 Y 轴的延伸距离,它们是不受变换矩阵所影响的。负值表示阴影会往上或左延伸,正值则表示会往下或右延伸,它们默认都为 0

shadowBlur = float

shadowBlur 用于设定阴影的模糊程度,其数值并不跟像素数量挂钩,也不受变换矩阵的影响,默认为 0

shadowColor = color

shadowColor 是标准的 CSS 颜色值,用于设定阴影颜色效果,默认是全透明的黑色。

第一步我们先绘制矩形,绘制矩形我们使用moveTo和lineTo,因为按钮一般是带有圆角的,所以我们封装一个绘制圆角矩形的

createPath: function (x, y, width, height, radius) {
            this.ctx.moveTo(x, y + radius);
            this.ctx.lineTo(x, y + height - radius);
            this.ctx.quadraticCurveTo(x, y + height, x + radius, y + height);
            this.ctx.lineTo(x + width - radius, y + height);
            this.ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius);
            this.ctx.lineTo(x + width, y + radius);
            this.ctx.quadraticCurveTo(x + width, y, x + width - radius, y);
            this.ctx.lineTo(x + radius, y);
            this.ctx.quadraticCurveTo(x, y, x, y + radius);
        },
复制代码

圆角矩形绘制完成后我们在接着绘制阴影,

setShadow: function (xoffset, yoffset) {
    var style = this.style;
    this.ctx.shadowOffsetX = xoffset || 0;
    this.ctx.shadowOffsetY = yoffset || 5;
    this.ctx.shadowBlur = 0;
    this.ctx.shadowColor = style.shadowColor;
},
复制代码

阴影绘制完后我们还要绘制文本,毕竟是canvas,绘制文本不像css那么方便,我们需要计算文字宽度来定位,代码如下:

drawText: function () {
     var xoffset = this.ctx.measureText(this.text).width;
     var x = this.x,
         y = this.y;
     if (this.state === 'active') {
         y = y + 5;
     }
     this.ctx.save();
     this.ctx.beginPath();
     this.ctx.font = "30px Micosoft yahei";
     this.ctx.fillStyle = this.fontColor;
     this.ctx.textBaseline = 'middle';
     this.ctx.textAlign = 'center';
     this.ctx.fillText(this.text, x + (this.width - xoffset) / 2 + 10, y + (this.height - 22) / 2 + 5, this.width);
     this.ctx.closePath();
     this.ctx.restore();
 },

复制代码

另附textAlign和textBaseLine的说明:

textAlign:

由canvas实现btn效果有感

textBaseLine:

由canvas实现btn效果有感

这样效果就基本大功告成了

由canvas实现btn效果有感

canvas事件可以具体看我的代码和我以前的博客

canvas发光效果

上面介绍了如何绘制canvas阴影立体按钮,接下来我们来实现试试更进一步的效果,多层阴影叠加效果,在css中我们的box-shadow可以叠加多层阴影效果,并且通过逗号分隔。那么我们canvas是不是也可以同样实现呢?我们知道canvas是基于状态的,我们如果要绘制多层阴影叠加,那么就需要保存每次绘制的阴影,层叠在一起,那么我们改下代码,每画一层阴影就需要保存一次canvas状态:

drawText: function (shadowx, shadowy, blur, shadowColor) {
            var xoffset = this.ctx.measureText(this.text).width;
            var x = this.x,
                y = this.y;
            this.ctx.save();
            this.ctx.beginPath();
            this.setShadow(shadowx, shadowy, blur, shadowColor);
            this.ctx.font = "300px Micosoft yahei";
            this.ctx.fillStyle = this.fontColor;
            this.ctx.textBaseline = 'middle';
            this.ctx.textAlign = 'center';
            this.ctx.fillText(this.text, x + (this.width - xoffset) / 2 + 10, y + (this.height - 22) / 2 + 5, this.width);
            this.ctx.closePath();
            this.ctx.restore();
        },
        
        setShadow: function (shadowx, shadowy, blur, shadowColor) {
            this.ctx.shadowOffsetX = shadowx || 0;
            this.ctx.shadowOffsetY = shadowy || 0;
            this.ctx.shadowBlur = blur || 10;
            this.ctx.shadowColor = shadowColor;
        },
复制代码

效果如下:

由canvas实现btn效果有感

不太完美,有时间在继续优化,动画的发光还是不太柔和,与css比效果还是有点欠缺,以后再优化,先mark一下,不喜勿喷。

总结

知识都是由互通性的,多学习多思考,不能学了这个忘那个,要能融会贯通(互相抄袭借鉴)

由canvas实现btn效果有感

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

O2O进化论

O2O进化论

板砖大余、姜亚东 / 中信出版社 / 2014-5 / 49

在互联网的1.0时代,Online的商业和Offline的商业就像是两条平行线,没有交汇点,在移动浪潮下,他们正在交汇,这就是O2O(Online to Offline)。于是,人们认为:O2O就是线下将线上作为销售前台。结论是对的,但并非简单相加就可以达到。人们已经进入数据革命时期,O2O是线上和线下全流通的数据化工具,电子商务就是非数据商品的数据化。其次,O2O还是一种竞争格局。这决定了以O2......一起来看看 《O2O进化论》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

SHA 加密
SHA 加密

SHA 加密工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器