本文實(shí)例為大家分享了fabricjs實(shí)現(xiàn)diy明信片功能的具體代碼,供大家參考,具體內(nèi)容如下
前言
要求需要添加,拷貝,刪除,雙指放大縮小。
提示:以下是本篇文章正文內(nèi)容,下面案例可供參考
一、fabric.js是一個(gè)很好用的 canvas 操作插件
示例:pandas 是基于NumPy 的一種工具,該工具是為了解決數(shù)據(jù)分析任務(wù)而創(chuàng)建的。
二、代碼示例
代碼如下(示例):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
|
<!DOCTYPE html> < html lang = "en" > < head > < title >diy</ title > < meta charset = "utf-8" > < meta name = "viewport" content = "user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1" > < meta http-equiv = "Access-Control-Allow-Origin" content = "*" /> < meta http-equiv = "Expires" content = "-1" > < meta http-equiv = "Cache-Control" content = "no-cache" > < meta http-equiv = "Pragma" content = "no-cache" > < script src = "./js/jquery-3.4.1.min.js" ></ script > < script src = "./js/fabric.js" ></ script > < script src = "./js/customiseControls.min.js" ></ script > </ head > < style > body{ margin: 0; padding: 0; border: 0; font-size: 100%; font-weight: normal; vertical-align: baseline; } .end{ position: fixed; top: 0; right: 0; width: 50px; height: 20px; background-color: #000000; color: #ffffff; font-size: 12px; line-height: 20px; z-index: 9999; } .canvasimg{ position: fixed; top: 0; left: 0; width: 50px; height: 20px; background-color: #000000; color: #ffffff; font-size: 12px; line-height: 20px; z-index: 9999; } .canvasimg input{ position: absolute; top: 0; left: 0; width: 100%; height: 100%; opacity: 0; } #inline-btn{ position: fixed; opacity: 0; z-index: 999; } #addinline-btn{ opacity: 0; position: fixed; z-index: 999; } .canvassrc{ position: fixed; top: 0; right: 0; width: 100%; height: 100%; z-index: 9999; } </ style > < body > < div class = "canvasimg" >< input type = "file" name = "" id = "canvasimg" class = "canvasimgadd" type = "file" accept = "image/*" onchange = "selectFileImage(this);" >添加圖片</ div > < div class = "end" onclick = "linkcanvas()" >生成圖片</ div > < button id = "inline-btn" onclick = "canvasonclick()" >刪除圖片按鈕</ button > < button id = "addinline-btn" onclick = "copy()" >復(fù)制圖片按鈕</ button > < canvas id = "c" ></ canvas > </ body > </ html > < script > //參考鏈接 //文末查看比較詳細(xì)的API中文解釋 //http://fabricjs.com/ fabric.js官網(wǎng) //diy功能需要有復(fù)制功能 刪除功能 放大縮小移動(dòng)旋轉(zhuǎn) //添加新圖片 function selectFileImage(fileObj){ var file = fileObj.files['0']; var reader = new FileReader(); reader.readAsDataURL(file) reader.onload = function (e){ fabric.Image.fromURL(e.target.result, function (img) { img.scale(1).set({ left: webwidth - (webwidth / 2),//圖片左右居中 top: webheight - (webheight / 2), //圖片上下居中 ,屏幕高度-(圖片高度/2)的總值/2 angle: 0, //角度為0 originX: 'center', originY: 'center', }); //圖片默認(rèn)寬度充滿屏幕一邊留白20 高度自適應(yīng) img.scaleToWidth(webwidth - 40) canvas.add(img).setActiveObject(img); //清除線條 img.hasBorders = false; //自定義圖片功能按鈕 , 隱藏多余功能按鈕,只保留4個(gè)角的按鈕 canvas.forEachObject(function (em) { em['setControlVisible']('mtr', false); em['setControlVisible']('mt', false); em['setControlVisible']('ml', false); em['setControlVisible']('mb', false); em['setControlVisible']('mr', false); em['setControlVisible']('mt', false); }) }); } } // 刪除按鈕 var btn = document.getElementById('inline-btn') // 添加按鈕 var addbtn = document.getElementById('addinline-btn') // 獲取屏幕高寬度 var webwidth = $(window).width() var webheight = $(window).height() //創(chuàng)建畫板 var canvas = new fabric.Canvas('c'); //canvas默認(rèn)充滿屏幕 canvas.setWidth(webwidth) canvas.setHeight(webheight) //導(dǎo)入圖片 fabric.Image.fromURL('./imgs/2.jpg', function (img) { img.scale(1).set({ left: webwidth - (webwidth/2),//圖片左右居中 top: webheight-(webheight/2), //圖片上下居中 ,屏幕高度-(圖片高度/2)的總值/2 angle: 0, //角度為0 originX: 'center', originY: 'center', }); //圖片默認(rèn)寬度充滿屏幕一邊留白20 高度自適應(yīng) img.scaleToWidth(webwidth-40) canvas.add(img).setActiveObject(img); //清除線條 img.hasBorders = false; //自定義圖片功能按鈕 , 隱藏多余功能按鈕,只保留4個(gè)角的按鈕 canvas.forEachObject(function(em){ em['setControlVisible']('mtr', false); em['setControlVisible']('mt', false); em['setControlVisible']('ml', false); em['setControlVisible']('mb', false); em['setControlVisible']('mr', false); em['setControlVisible']('mt', false); }) }); //取消多選 canvas.selection = false; //新建圖層不出現(xiàn)在頂層 canvas.preserveObjectStacking = true; //注:要自定義修改按鈕功能需要引入fabric的另一個(gè)叫customiseControls的JS插件 否則無法操作 //全局修改4個(gè)按鈕的功能 fabric.Canvas.prototype.customiseControls({ bl: { action: 'rotate' //添加圖片旋轉(zhuǎn)功能 }, // only is hasRotatingPoint is not set to false }, function () { canvas.renderAll(); }); //因?yàn)槟J(rèn)的按鈕樣式不是我們想要的 所以需要自定義一些icon在上面 fabric.Object.prototype.customiseCornerIcons({ tl: { icon: './img/+1@2x.png', //圖片路徑 cornerSize: 70, //按鈕點(diǎn)擊范圍 相當(dāng)于css的padding屬性 settings: { cornerSize: 25 //icon大小 }, }, tr: { icon: './img/X@2x.png', cornerSize: 70, settings: { cornerSize: 25 }, }, bl: { icon: './img/xuanzhuan@2x.png', cornerSize: 70, settings: { cornerSize: 25 }, }, br: { icon: './img/fangda@2x.png', cornerSize: 70, settings: { cornerSize: 25 }, }, }, function () { canvas.renderAll(); }); //按鈕跟隨圖片定位 function positionBtn(obj) { //獲取當(dāng)前選中圖片單位參數(shù) var absCoords = canvas.getAbsoluteCoords(obj); btn.style.width = '30px'; btn.style.height = '30px'; btn.style.opacity = '0'; btn.style.left = (absCoords.right - 30 / 2) + 'px'; btn.style.top = (absCoords.top - 30 / 2) + 'px'; addbtn.style.width = '30px'; addbtn.style.height = '30px'; addbtn.style.opacity = '0'; addbtn.style.left = (absCoords.left - 30 / 2) + 'px'; addbtn.style.top = (absCoords.leftTop - 30 / 2) + 'px'; } fabric.Canvas.prototype.getAbsoluteCoords = function (object) { return { right: object.aCoords.tr.x + this._offset.left, top:object.aCoords.tr.y + this._offset.top, left: object.aCoords.tl.x + this._offset.left, leftTop: object.aCoords.tl.y + this._offset.top, }; } //刪除當(dāng)前選中圖片 function canvasonclick(){ var t = canvas.getActiveObject() canvas.remove(t); } //拷貝當(dāng)前選中圖片 function copy(){ var _self = this; canvas.getActiveObject().clone(function (cloned) { _self.paste(cloned); canvas.discardActiveObject().renderAll() }) } function paste(_clipboard){ console.log(_clipboard) var t = canvas.getActiveObject(); // 再次克隆,這樣你就可以復(fù)制多個(gè)副本。 t.clone(function (clonedObj) { canvas.discardActiveObject(); clonedObj.set({ left: clonedObj.left + 20, top: clonedObj.top + 20, evented: true, hasBorders:false }); if (clonedObj.type === 'activeSelection') { // 活動(dòng)選擇需要對畫布的引用。 clonedObj.canvas = canvas; clonedObj.forEachObject(function (obj) { canvas.add(obj); canvas.forEachObject(function (em) { em['setControlVisible']('mtr', false); em['setControlVisible']('mt', false); em['setControlVisible']('ml', false); em['setControlVisible']('mb', false); em['setControlVisible']('mr', false); em['setControlVisible']('mt', false); }) }); // 解決不可選擇的問題 clonedObj.setCoords(); } else { canvas.add(clonedObj); canvas.forEachObject(function (em) { em['setControlVisible']('mtr', false); em['setControlVisible']('mt', false); em['setControlVisible']('ml', false); em['setControlVisible']('mb', false); em['setControlVisible']('mr', false); em['setControlVisible']('mt', false); }) } }); } var store = {} //計(jì)算平均值 var getDistance = function (start, stop) { return Math.hypot(stop.x - start.x, stop.y - start.y); }; //監(jiān)聽positionBtn事件 鼠標(biāo)以上點(diǎn)擊圖片時(shí)移動(dòng)時(shí)觸發(fā)我們自定義的復(fù)制按鈕和刪除按鈕跟隨圖片定位以及雙指放大縮小功能 canvas.on('mouse:down',function(options){ //判斷是否點(diǎn)擊到了圖片單位 if(options.target){ //運(yùn)行事件 positionBtn(options.target); //雙指放大縮小 store.pageX = options.e.changedTouches[0].clientX store.pageY = options.e.changedTouches[0].clientY if (options.e.changedTouches.length == 2) { store.pageY2 = options.e.changedTouches[1].clientY store.pageX2 = options.e.changedTouches[1].clientX } store.originScale = options.target.scaleX || 0.5; store.originleft = options.target.left; store.origintop = options.target.top; } }); canvas.on('mouse:move',function(options){ if(options.target){ positionBtn(options.target); if (options.e.changedTouches.length == 2) { if (!store.pageX2) { store.pageX2 = options.e.changedTouches[1].clientX } if (!store.pageY2) { store.pageY2 = options.e.changedTouches[1].clientY } var zoom = getDistance({ x: options.e.changedTouches[0].clientX, y: options.e.changedTouches[0].clientY }, { x: options.e.changedTouches[1].clientX, y: options.e.changedTouches[1].clientY }) / getDistance({ x: store.pageX, y: store.pageY }, { x: store.pageX2, y: store.pageY2 }); var newScale = store.originScale * zoom; if (newScale > 3) { newScale = 3; } options.target.scaleX = newScale; options.target.scaleY = newScale; canvas.renderAll(); } } }); canvas.on('mouse:up',function(options){ if(options.target){ positionBtn(options.target); store.pageY = 0 store.pageX = 0 store.pageY2 = 0 store.pageX2 = 0 store.originScale = options.target.scaleX store.originleft = options.target.left store.origintop = options.target.top } }); //生成明信片 function linkcanvas(){ let xheight = $('#c').height() let xwidth = $('#c').width() canvas.setBackgroundColor('rgba(255, 255, 255, 1)', canvas.renderAll.bind(canvas)); var exportedArt = this.canvas.toDataURL({ format: "jpeg", quality: 1.0, multiplier: 2.4, left: 0, top: 0, width: xwidth, height: xheight, }); $('body').append(`< img class = "canvassrc" src = "${exportedArt}" />`) } </ script > |
實(shí)現(xiàn)效果
總結(jié)
具體一些方法知識點(diǎn)建議大家可以去參考一下這篇文章
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:https://blog.csdn.net/C491114088/article/details/114871216