fabric.js實(shí)現(xiàn)diy明信片功能
本文實(shí)例為大家分享了fabricjs實(shí)現(xiàn)diy明信片功能的具體代碼,供大家參考,具體內(nèi)容如下
前言
要求需要添加,拷貝,刪除,雙指放大縮小。
提示:以下是本篇文章正文內(nèi)容,下面案例可供參考
一、fabric.js是一個(gè)很好用的 canvas 操作插件
示例:pandas 是基于NumPy 的一種工具,該工具是為了解決數(shù)據(jù)分析任務(wù)而創(chuàng)建的。
二、代碼示例
代碼如下(示例):
<!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)選擇需要對(duì)畫布的引用。
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é)
具體一些方法知識(shí)點(diǎn)建議大家可以去參考一下這篇文章
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
js實(shí)現(xiàn)獲取焦點(diǎn)后光標(biāo)在字符串后
這篇文章主要介紹了js實(shí)現(xiàn)獲取焦點(diǎn)后光標(biāo)在字符串后,原理就是獲得焦點(diǎn)后重新把自己復(fù)制粘帖一下,喜歡的朋友可以看看2014-09-09
JavaScript中檢查對(duì)象property的存在性方法介紹
這篇文章主要介紹了JavaScript中檢查對(duì)象property的存在性方法介紹,本文講解了4種方法來檢查某個(gè)對(duì)象o是否擁有property x,需要的朋友可以參考下2014-12-12
Microsoft Ajax Minifier 壓縮javascript的方法
使用Microsoft AJAX 庫 (第六個(gè)預(yù)覽版) 其中有一個(gè) ajaxmin.exe 可以壓縮Js文件可以在dos 命令下 /? 查看其參數(shù)說明。2010-03-03
JavaScript 報(bào)表展示實(shí)現(xiàn)代碼
以下是從網(wǎng)上找到的一段JavaScript實(shí)現(xiàn)圖形報(bào)表的代碼,對(duì)于想客戶端顯示報(bào)表的朋友可以參考下。2009-12-12
uniapp實(shí)現(xiàn)全局變量的幾種方式總結(jié)
這里說全局變量,著重指的是能夠全局動(dòng)態(tài)響應(yīng)的情況,下面這篇文章主要給大家介紹了關(guān)于uniapp實(shí)現(xiàn)全局變量的幾種方式,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-10-10
uniapp 引用 js 組件的方法(場(chǎng)景分析)
在UniApp開發(fā)過程中,我們不僅需要掌握各種UI組件的使用方法,還需要了解如何在項(xiàng)目中引入JS文件,在本文中,我將介紹UniApp中如何引入JS的方法,感興趣的朋友跟隨小編一起看看吧2023-09-09

