今天项目中牵涉到一个html图片生成的需求,然后就发现了这个第三方的js -- html2canvas
PS: 附上官方使用文档 http://html2canvas.hertzen.com/
①引入JS
可以在官方下载,也可以使用CDN
②在需要的html中指定操作元素
<div id="capture" style="padding:2rem;">
// your code ...
</div>
③调用指定的方法
export(){
html2canvas(document.querySelector("#capture")).then(canvas => {
saveFile(canvas.toDataURL(),"ccc.png");
});
}
saveFile(data, filename){
const save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
save_link.href = data;
save_link.download = filename;
const event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
save_link.dispatchEvent(event);
};
源于公众号前埔寨 ,
作者荣顶
我们想在画布上画个基本的简单形状的时候,使用 Canvas 不会觉得有什么繁琐。但当画布上需要任何形式的互动,绘制复杂的图形和在特定情况需要改变图片的时候,使用原生 canvas API 将会变得很困难。
而 Fabric 旨在解决这个问题。
Fabric.js 是一个强大而简单的 Javascript HTML5 画布库 Fabric 在画布元素之上提供交互式对象模型 Fabric 还具有 SVG-to-canvas(和 canvas-to-SVG)解析器
为了方便,下面我将通过 vue项目 为大家讲解如何使用 Fabric
yarn add fabric -S
#or
npm i fabric -S
也可以在 官网 下载最新 js 文件,通过 script 标签引入
<!-- html -->
<canvas id="canvas" width="500" height="500"></canvas>
Fabric 提供了 7 种基础形状:
fabric.Circle (圆)
fabric.Ellipse (椭圆)
fabric.Line (线)
fabric.Polyline (多条线绘制成图形)
fabric.triangle (三角形)
fabric.Rect (矩形)
fabric.Polygon (多边形)
//引入fabric
import { fabric } from "fabric";
// 创建一个fabric实例
let canvas = new fabric.Canvas("canvas"); //可以通过鼠标方法缩小,旋转
// or
// let canvas = new fabric.StaticCanvas("canvas");//没有鼠标交互的fabric对象
// 创建一个矩形对象
let rect = new fabric.Rect({
left: 200, //距离左边的距离
top: 200, //距离上边的距离
fill: "green", //填充的颜色
width: 200, //矩形宽度
height: 200, //矩形高度
});
// 将矩形添加到canvas画布上
canvas.add(rect);
可以看到界面中填充了一个可以通过鼠标放大缩小且可以旋转的绿色矩形
通过对象的形式配置元素样式,非常的方便!
let circle = new fabric.Circle({
left: 0, //距离左边的距离
top: 0, //距离上边的距离
fill: "red", //填充的颜色
radius: 50, //圆的半径
});
// 创建一个三角形对象
let triangle = new fabric.Triangle({
left: 200, //距离左边的距离
top: 0, //距离上边的距离
fill: "blue", //填充的颜色
width: 100, //宽度
height: 100, //高度
});
// 将图形形添加到canvas画布上
canvas.add(circle, triangle);
我们可以通过以下属性设置,决定是否可以对相关元素进行交互
rect.set("selectable", false); // 只是禁止这个矩形选中
主要有通过 url 和 img 标签绘制两种方式
fabric.Image.fromURL(
//本地图片需要通过require来引入,require("./xxx.jpeg")
"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.thaihot.com.cn%2Fuploadimg%2Fico%2F2021%2F0711%2F1625982535739193.jpg&refer=http%3A%2F%2Fimg.thaihot.com.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1630940858&t=e1d24ff0a7eaeea2ff89cedf656a9374",
(img) => {
img.scale(0.5);
canvas.add(img);
}
);
//也可以通过标签绘制
let img = document.getElementById("img");
let image = new fabric.Image(img, {
left: 100,
top: 100,
opacity: 0.8,
});
canvas.add(image);
在此之前我们需要了解几个参数的含义
customPath.set({
left: 100,
top: 100,
fill: "green",
});
canvas.add(customPath);
"M 0 0 L 300 100 L 170 100 L 70 300 L 20 200 C136.19,2.98,128.98,0,121.32,0 z"
);
可以看到通过路径绘制,我们可以制作非常复杂的图形(但是一般用不到,我们一般用它来解析 SVG 后拿到 path 复原图形)
第一个参数是动画的属性,第二个参数是动画的最终位置,第三个参数是一个可选的对象,指定动画的细节:持续时间,回调,动效等。
第三个参数主要有
duration 默认为 500ms。可以用来改变动画的持续时间。
from 允许指定动画属性的起始值(如果我们不希望使用当前值)。
onComplete 动画结束之后的回调。
easing 动效函数。
let rect = new fabric.Rect({
left: 400, //距离左边的距离
top: 200, //距离上边的距离
fill: "green", //填充的颜色
width: 200, //宽度
height: 200, //高度
});
rect.animate("left", 100, {
onChange: canvas.renderAll.bind(canvas),
duration: 1000,
});
canvas.add(rect);
onChange: canvas.renderAll.bind(canvas),
duration: 1000,
});
rect.animate("angle", "-=90", {
onChange: canvas.renderAll.bind(canvas),
duration: 2000,
});
默认情况下,动画使用“easeInSine”动效执行。如果这不是你需要的,fabric 为我们提供了很多内置动画效果, fabric.util.ease 下有一大堆动效的选项。
常用的有easeOutBounce,easeInCubic,easeOutCubic,easeInElastic,easeOutElastic,easeInBounce 和 easeOutExpo等
onChange: canvas.renderAll.bind(canvas),
duration: 1000,
easing: fabric.util.ease.easeOutBounce,
});
目前 Fabric 为我们提供了以下内置滤镜
img.scale(0.5);
canvas.add(img);
});
fabric.Image.fromURL(require("./aaa.jpeg"), (img) => {
img.scale(0.5);
// 添加滤镜
img.filters.push(new fabric.Image.filters.Grayscale());
// 图片加载完成之后,应用滤镜效果
img.applyFilters();
img.set({
left: 300,
top: 250,
});
canvas.add(img);
});
“filters”属性是一个数组,我们可以用数组方法执行任何所需的操作:移除滤镜(pop,splice,shift),添加滤镜(push,unshift,splice),甚至可以组合多个滤镜。当我们调用 applyFilters 时,“filters”数组中存在的任何滤镜将逐个应用,所以让我们尝试创建一个既色偏又明亮(Brightness)的图像。
img.scale(0.5);
// 添加滤镜
img.filters.push(
new fabric.Image.filters.Grayscale(),
new fabric.Image.filters.Sepia(), //色偏
new fabric.Image.filters.Brightness({ brightness: 0.2 }) //亮度
);
// 图片加载完成之后,应用滤镜效果
img.applyFilters();
img.set({
left: 300,
top: 250,
});
canvas.add(img);
});
可以看到多个滤镜的效果叠加显示了,当然 Fabric 还支持自定义滤镜,在本篇文章点赞过 500 后我将更新 fabric 高级篇,感谢大家的支持~
无论你是使用十六进制,RGB 或 RGBA 颜色,Fabric 都能处理的很好
new fabric.Color("#aa3123");
new fabric.Color("356333");
new fabric.Color("rgb(100,50,100)");
new fabric.Color("rgba(100, 200, 30, 0.5)");
new fabric.Color('rgb(100,100,100)').toHex(); // "646464"
new fabric.Color('fff').toHex(); // "FFFFFF"
我们还可以用另一种颜色叠加,或将其转换为灰度版本。
let greenish = new fabric.Color("#5f5");
redish.overlayWith(greenish).toHex(); // "AAAA55"
redish.toGrayscale().toHex(); // "A1A1A1"
Fabric 通过 setGradient 方法支持渐变,在所有对象上定义。调用 setGradient('fill', { ... })就像设置一个对象的“fill”值一样。
left: 100,
top: 100,
radius: 50
});
circle.setGradient("fill", {
// 渐变开始的位置
x1: 0,
y1: 0,
// 渐变结束的位置
x2: circle.width,
y2: 0,
//渐变的颜色
colorStops: {
// 渐变的范围(0,0.1,0.3,0.5,0.75,1)0-1之间都可以
0: "red",
0.2: "orange",
0.4: "yellow",
0.6: "green",
0.8: "blue",
1: "purple"
},
});
fabric.Text 对象对于文本,提供了比 canvas 更丰富的功能,包括:
支持多行 Multiline support 不幸的是,原生文本方法忽略了新建一行。
文本对齐 Text alignment 左,中,右。使用多行文本时很有用。
文本背景 Text background 背景也支持文本对齐。
文字装饰 Text decoration 下划线,上划线,贯穿线。
行高 Line Height 在使用多行文本时有用。
字符间距 Char spacing 使文本更紧凑或更间隔。
子范围 Subranges 将颜色和属性应用到文本对象的子对象中。
多字节 Multibyte 支持表情符号。
交互式画布编辑 On canvas editing 可以直接在画布上键入文本。
"大家好~这里是前埔寨\n我是荣顶~\n一个要成为开发王的男人!",
{
left: 0,
top: 200,
fontFamily: "Comic Sans", //字体
fontSize: 50, //字号
fontWeight: 800, //字体粗细,可以使用关键字(“normal”,“bold”)或数字(100,200,400,600,800)
shadow: "green 3px 3px 2px", //文字阴影,颜色,水平偏移,垂直偏移和模糊大小。
underline: true, //下划线
linethrough: true, //删除线
overline: true, //上划线
fontStyle: "italic", //字体风格,normal(正常)或italic(斜体)
stroke: "#c3bfbf", //描边的颜色
strokeWidth: 1, //描边的宽度
textAlign: "center", //文本对齐方式
lineHeight: 1.5, //行高
textBackgroundColor: "#91A8D0", //文本背景颜色
}
);
canvas.add(text);
fabric 中通过 on 方法来初始化事件,off 方法用来删除事件。常用的事件有以下
还有一大堆:
鼠标事件:“mouse:down” ,“mouse:move”和“mouse:up...” 选择相关的事件:“before:selection:cleared”, “selection:created”, 详细的可以查看 官方文档
canvas.clear();
let text = new fabric.Text("你点我啦~", {
left: 200,
top: 200,
});
canvas.add(text);
console.log(options.e.clientX, options.e.clientY);
});
canvas.on("mouse:up", function(options) {
this.text = "你没点我0.0";
canvas.clear();
let text = new fabric.Text("你没点我0.0", {
left: 200,
top: 200,
});
canvas.add(text);
console.log(options.e.clientX, options.e.clientY);
});
Fabric 允许将侦听器直接附加到 canvas 画布中的对象上。
rect.on("selected", function() {
console.log("哦吼~你选择了我");
});
let circle = new fabric.Circle({ radius: 75, fill: "blue" });
circle.on("selected", function() {
console.log("哈哈哈~你选择了我");
});
Fabric canvas 的 isDrawingMode 属性设置为 true 即可实现自由绘制模式.
这样画布上的点击和移动就会被立刻解释为铅笔或刷子。
canvas.isDrawingMode = true;
canvas.freeDrawingBrush.color = "blue";
canvas.freeDrawingBrush.width = 5;
很开心写下这篇文章,它是我用来总结归纳 fabric 的知识点,并且非常用心的一篇文章,希望这篇文章对你有所帮助。目前 fabric 在国内还不是很火,但是 github 上已经有 19.2k 的 star 了,也算是一个明星项目。我们日常开发经常会用到 canvas,但是它的 api 对于处理复杂的业务逻辑会令人感到非常的劳累,分享这篇文章,希望对大家有所帮助!
VG 动画有很多种实现方法,也有很大SVG动画库,现在我们就来介绍 svg动画实现方法都有哪些?
SVG animation 有五大元素,他们控制着各种不同类型的动画,分别为:
1.1、set
set 为动画元素设置延迟,此元素是SVG中最简单的动画元素,但是他并没有动画效果。
使用语法:
<set attributeName="" attributeType="" to="" begin="" />
eg:绘制一个半径为200的圆,4秒之后,半径变为50。
<svg width="320" height="320">
<circle cx="0" cy="0" r="200" style="stroke: none; fill: #0000ff;">
<set attributeName="r" attributeType="XML" to="50" begin="4s" />
</circle>
</svg>
1.2、animate
是基础的动画元素,实现单属性的过渡效果。
使用语法:
<animate
attributeName="r"
from="200" to="50"
begin="4s" dur="2s"
repeatCount="2"
></animate>
eg:绘制一个半径为200的圆,4秒之后半径在2秒内从200逐渐变为50。
<circle cx="0" cy="0" r="200" style="stroke: none; fill: #0000ff;">
<animate attributeName="r" from="200" to="50"
begin="4s" dur="2s" repeatCount="2"></animate>
</circle>
1.3、animateColor
控制颜色动画,animate也可以实现这个效果,所以该属性目前已被废弃。
1.4、animateTransform
实现transform变换动画效果,与css3的transform变换类似。实现平移、旋转、缩放等效果。
使用语法:
<animateTransform attributeName="transform" type="scale"
from="1.5" to="0"
begin="2s" dur="3s"
repeatCount="indefinite"></animateTransform>
<svg width="320" height="320">
<circle cx="0" cy="0" r="200" style="stroke: none; fill: #0000ff;">
<animateTransform attributeName="transform" begin="4s"
dur="2s" type="scale" from="1.5" to="0"
repeatCount="indefinite"></animateTransform>
</circle>
</svg>
1.5、animateMotion
可以定义动画路径,让SVG各个图形,沿着指定路径运动。
使用语法:
<animateMotion
path="M 0 0 L 320 320"
begin="4s" dur="2s"></animateMotion>
eg:绘制一个半径为10的圆,延迟4秒从左上角运动的右下角。
<svg width="320" height="320">
<circle cx="0" cy="0" r="10" style="stroke: none; fill: #0000ff;">
<animateMotion
path="M 0 0 L 320 320"
begin="4s" dur="2s"
></animateMotion>
</circle>
</svg>
实际制作动画的时候,动画太单一不酷,需要同时改变多个属性时,上边的四种元素可以互相组合,同类型的动画也能组合。以上这些元素虽然能够实现动画,但是无法动态地添加事件,所以接下来我们就看看 js 如何制作动画。
上篇文章我们介绍js可以操作path,同样也可以操作SVG的内置形状元素,还可以给任意元素添加事件。
给SVG元素添加事件方法与普通元素一样,可以只用on+事件名 或者addEventListener添加。
eg:使用SVG绘制地一条线,点击线条地时候改变 x1 ,实现旋转效果。
<svg width="800" height="800" id="svg">
<line id="line" x1="100" y1="100"
x2="400" y2="300"
stroke="black" stroke-width="5"></line>
</svg>
<script>
window.onload = function(){
var line = document.getElementById("line")
line.onclick = function(){
let start = parseInt(line.getAttribute("x1")),
end=400,dis = start-end
requestAnimationFrame(next)
let count = 0;
function next(){
count++
let a = count/200,cur = Math.abs(start+ dis*a)
line.setAttribute('x1',cur)
if(count<200)requestAnimationFrame(next)
}
}
}
</script>
js制作的SVG动画,主要利用 requestAnimationFrame 来实现一帧一帧的改变。
我们上述制作的 SVG 图形、动画等,运行在低版本IE中,发现SVG只有IE9以上才支持,低版本的并不能支持,为了兼容低版本浏览器,可以使用 VML ,VML需要添加额外东西,每个元素需要添加 v:元素,样式中还需要添加 behavier ,经常用于绘制地图。由于使用太麻烦,所以我们借助 Raphael.js 库。
Raphael.js是通过SVG/VML+js实现跨浏览器的矢量图形,在IE浏览器中使用VML,非IE浏览器使用SVG,类似于jquery,本质还是一个javascript库,使用简单,容易上手。
使用之前需要先引入Raphael.js库文件。cdn的地址为:https://cdn.bootcdn.net/ajax/libs/raphael/2.3.0/raphael.js
3.1、创建画布
Rapheal有两种创建画布的方式:
第一种:浏览器窗口上创建画布
创建语法:
var paper = Raphael(x,y,width,height)
x,y是画布左上角的坐标,此时画布的位置是绝对定位,有可能会与其他html元素重叠。width、height是画布的宽高。
第二种:在一个元素中创建画布
创建语法:
var paper = Raphael(element, width, height);
element是元素节点本身或ID width、height是画布的宽度和高度。
3.2、绘制图形
画布创建好之后,该对象自带SVG内置图形有矩形、圆形、椭圆形。他们的方法分别为:
paper.circle(cx, cy, r); // (cx , cy)圆心坐标 r 半径
paper.rect(x, y, width, height, r); // (x,y)左上角坐标 width宽度 height高度 r圆角半径(可选)
paper. ellipse(cx, cy, rx, ry); // (cx , cy)圆心坐标 rx水平半径 ry垂直半径
eg:在div中绘制一个圆形,一个椭圆、一个矩形。
<div id="box"></div>
<script>
var paper = Raphael("box",300,300)
paper.circle(150,150,150)
paper.rect(0,0,300,300)
paper.ellipse(150,150,100,150)
</script>
运行结果如下:
除了简单图形之外,还可以绘制复杂图形,如三角形、心型,这时就使用path方法。
使用语法:paper.path(pathString)
pathString是由一个或多个命令组成,每个命令以字母开始,多个参数是由逗号分隔。
eg:绘制一个三角形。
let sj = paper.path("M 0,0 L100,100 L100,0 'Z'")
还可以绘制文字,如果需要换行,使用 \n 。
文字语法:paper.text(x,y,text)
(x,y)是文字坐标,text是要绘制的文字。
3.3、设置属性
图形绘制之后,我们通常会添加stroke、fill、stroke-width等让图形更美观,Raphael使用attr给图形设置属性。
使用语法:circle.attr({"属性名","属性值","属性名","属性值",...})
如果只有属性名没有属性值,则是获取属性,如果有属性值,则是设置属性。
注意:如果只设置一个属性时,可以省略‘{}’。如:rect.attr('fill','pink')
eg:给上边的矩形添加边框和背景色。
<div id="box"></div>
<script>
var paper = Raphael("box",300,300)
let rect = paper.rect(100,100,150,200)
rect.attr({'fill':'red','stroke':'blue','stroke-width':'10'})
</script>
3.4、添加事件
RaphaelJS一般具有以下事件:
click、dblclick、drag、hide、hover、mousedown、mouseout、mouseup、mouseover等以及对应的解除事件,只要在前面加上“un”就可以了(unclick、undblclick)。
使用语法:
obj.click(function(){
//需要操作的内容
})
3.5、添加动画
animate为指定图形添加动画并执行。
使用语法:
obj.animate({
"属性名1":属性值1,
"属性名2":属性值2,
...
},time,type)
属性名和属性值就根据你想要的动画类型加就ok。
time:动画所需时间。
type:指动画缓动类型。常用值有:
eg:点击矩形,矩形缓缓变大。
<div id="box"></div>
<script>
var paper = Raphael("box",800,500)
let rect = paper.rect(100,100,150,100)
rect.attr({'fill':'red','stroke':'blue','stroke-width':'10'})
rect.attr('fill','pink')
rect.click(function(){
rect.animate({
"width":300,
"height":300
},1000,"bounce")
})
</script>
复制上边的代码,分别在各个浏览器和低版本IE浏览器运行,发现都可以正常运行。SVG的动画库挺多了,我们介绍了拉斐尔,有兴趣的小伙伴可以自行找找其他库。
*请认真填写需求信息,我们会在24小时内与您取得联系。