今天項目中牽涉到一個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小時內與您取得聯系。