【问题标题】:Add background image with fabric.js使用 fabric.js 添加背景图片
【发布时间】:2017-10-16 01:01:39
【问题描述】:

我可以使用输入 type="file" id="file" 添加图像,但是希望能够上传可以移动的图像并作为背景图像保留在所有其他图像后面。现在我可以添加一些东西并将其发送到后面,但移动它很困难,因为控件从画布上跑了出来。任何帮助将不胜感激 - 在此先感谢。

// Add image from local
var canvas = new fabric.Canvas('c');

// display/hide text controls
canvas.on('object:selected', function(e) {
  if (e.target.type === 'i-text') {
    document.getElementById('textControls').hidden = false;
  }
});
canvas.on('before:selection:cleared', function(e) {
  if (e.target.type === 'i-text') {
    document.getElementById('textControls').hidden = true;
  }
});
document.getElementById('file').addEventListener("change", function(e) {
  var file = e.target.files[0];
  var reader = new FileReader();
  reader.onload = function(f) {
    var data = f.target.result;
    fabric.Image.fromURL(data, function(img) {
      var oImg = img.set({
        left: 0,
        top: 0,
        angle: 00,
        border: '#000',
        stroke: '#F0F0F0', //<-- set this
        strokeWidth: 40 //<-- set this
      }).scale(0.2);
      canvas.add(oImg).renderAll();
      //var a = canvas.setActiveObject(oImg);
      var dataURL = canvas.toDataURL({
        format: 'png',
        quality: 1
      });
    });
  };
  reader.readAsDataURL(file);
});
// Delete selected object
window.deleteObject = function() {
  var activeGroup = canvas.getActiveGroup();
  if (activeGroup) {
    var activeObjects = activeGroup.getObjects();
    for (let i in activeObjects) {
      canvas.remove(activeObjects[i]);
    }
    canvas.discardActiveGroup();
    canvas.renderAll();
  } else canvas.getActiveObject().remove();
}
// Refresh page
function refresh() {
  setTimeout(function() {
    location.reload()
  }, 100);
}
// Add text
function Addtext() {
  canvas.add(new fabric.IText('Tap and Type', {
    left: 50,
    top: 100,
    fontFamily: 'helvetica neue',
    fill: '#000',
    stroke: '#fff',
    strokeWidth: .1,
    fontSize: 45
  }));
}
// Edit Text
document.getElementById('text-color').onchange = function() {
  canvas.getActiveObject().setFill(this.value);
  canvas.renderAll();
};
document.getElementById('text-color').onchange = function() {
  canvas.getActiveObject().setFill(this.value);
  canvas.renderAll();
};
document.getElementById('text-bg-color').onchange = function() {
  canvas.getActiveObject().setBackgroundColor(this.value);
  canvas.renderAll();
};
document.getElementById('text-lines-bg-color').onchange = function() {
  canvas.getActiveObject().setTextBackgroundColor(this.value);
  canvas.renderAll();
};
document.getElementById('text-stroke-color').onchange = function() {
  canvas.getActiveObject().setStroke(this.value);
  canvas.renderAll();
};
document.getElementById('text-stroke-width').onchange = function() {
  canvas.getActiveObject().setStrokeWidth(this.value);
  canvas.renderAll();
};
document.getElementById('font-family').onchange = function() {
  canvas.getActiveObject().setFontFamily(this.value);
  canvas.renderAll();
};
document.getElementById('text-font-size').onchange = function() {
  canvas.getActiveObject().setFontSize(this.value);
  canvas.renderAll();
};
document.getElementById('text-line-height').onchange = function() {
  canvas.getActiveObject().setLineHeight(this.value);
  canvas.renderAll();
};
document.getElementById('text-align').onchange = function() {
  canvas.getActiveObject().setTextAlign(this.value);
  canvas.renderAll();
};
radios5 = document.getElementsByName("fonttype"); // wijzig naar button
for (var i = 0, max = radios5.length; i < max; i++) {
  radios5[i].onclick = function() {
    if (document.getElementById(this.id).checked == true) {
      if (this.id == "text-cmd-bold") {
        canvas.getActiveObject().set("fontWeight", "bold");
      }
      if (this.id == "text-cmd-italic") {
        canvas.getActiveObject().set("fontStyle", "italic");
      }
      if (this.id == "text-cmd-underline") {
        canvas.getActiveObject().set("textDecoration", "underline");
      }
      if (this.id == "text-cmd-linethrough") {
        canvas.getActiveObject().set("textDecoration", "line-through");
      }
      if (this.id == "text-cmd-overline") {
        canvas.getActiveObject().set("textDecoration", "overline");
      }
    } else {
      if (this.id == "text-cmd-bold") {
        canvas.getActiveObject().set("fontWeight", "");
      }
      if (this.id == "text-cmd-italic") {
        canvas.getActiveObject().set("fontStyle", "");
      }
      if (this.id == "text-cmd-underline") {
        canvas.getActiveObject().set("textDecoration", "");
      }
      if (this.id == "text-cmd-linethrough") {
        canvas.getActiveObject().set("textDecoration", "");
      }
      if (this.id == "text-cmd-overline") {
        canvas.getActiveObject().set("textDecoration", "");
      }
    }
    canvas.renderAll();
  }
}

// Send selected object to front or back
var selectedObject;
canvas.on('object:selected', function(event) {
  selectedObject = event.target;
});
var sendSelectedObjectBack = function() {
  canvas.sendToBack(selectedObject);
}
var sendSelectedObjectToFront = function() {
  canvas.bringToFront(selectedObject);
}
// Download
var imageSaver = document.getElementById('lnkDownload');
imageSaver.addEventListener('click', saveImage, false);

function saveImage(e) {
  this.href = canvas.toDataURL({
    format: 'png',
    quality: 0.8
  });
  this.download = 'custom.png'
}
// Do some initializing stuff
fabric.Object.prototype.set({
  transparentCorners: true,
  cornerColor: '#22A7F0',
  borderColor: '#22A7F0',
  cornerSize: 12,
  padding: 5
});
body {
  padding: 10px 10px 10px 10px;
  font-family: "HelveticaNeue";
}

canvas {
  border: 1px solid #bdc3c7;
  margin: 10px 0px 0px 0px;
  /*  background-image: url("images/bg.png"); */
}

.myFile {
  position: relative;
  overflow: hidden;
  float: left;
  clear: left;
}

.myFile input[type="file"] {
  display: block;
  position: absolute;
  top: 0;
  right: 0;
  opacity: 0;
  font-size: 30px;
  filter: alpha(opacity=0);
}

.title {
  color: black;
  text-decoration: none;
  margin-bottom: 20px;
  display: block;
}

hr {
  text-align: left;
  margin: 30px auto 0 0;
  width: 700px;
}

a:visited {
  text-decoration: none;
  color: #000;
}

a:active {
  text-decoration: none;
  color: #000;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.11/fabric.js"></script>
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <title>Brand</title>
  <link rel="stylesheet" type="text/css" href="styles.css">
  <link rel="stylesheet" type="text/css" href="icons/css/materialdesignicons.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>

<body>
  <label><a style="text-decoration: none;" href="#"><span class="mdi mdi-lightbulb-on-outline">Brand</span></a></label><br><br>
  <label title="Add an image" class="myFile"><span class="mdi mdi-image"> Add Photo</span>&nbsp;<input type="file" id="file" /></label>
  <a onclick="Addtext()" title="Add text"><span class="mdi mdi-format-text"> Add Text</span></a>&emsp;
  <a onclick="sendSelectedObjectToFront()" title="Bring selected to front"><span class="mdi mdi-arrange-bring-forward"> Front</span></a>
  <a onclick="sendSelectedObjectBack()" title="Send selected to back"><span class="mdi mdi-arrange-send-backward"> Back</span></a>
  <a onClick="deleteObject()" title="Delete Anything Selected"><span class="mdi mdi-delete"> Delete</span></a>&emsp;
  <a onclick="refresh()" title="Start fresh"><span class="mdi mdi-shredder"> Clear All</span></a>&emsp;
  <a id="lnkDownload" title="Save"><span class="mdi mdi-download"> Save</span></a>
  <div id="textControls" hidden>
    <div id="text-wrapper" data-ng-show="getText()">
      <div id="text-controls">
        <select id="font-family">
            <option value="arial">Arial</option>
            <option value="HelveticaNeue" selected>Helvetica Neue</option>
            <option value="myriad pro">Myriad Pro</option>
            <option value="delicious">Delicious</option>
            <option value="verdana">Verdana</option>
            <option value="georgia">Georgia</option>
            <option value="courier">Courier</option>
            <option value="comic sans ms">Comic Sans MS</option>
            <option value="impact">Impact</option>
            <option value="monaco">Monaco</option>
            <option value="optima">Optima</option>
            <option value="hoefler text">Hoefler Text</option>
            <option value="plaster">Plaster</option>
            <option value="engagement">Engagement</option>
          </select>
        <input type="color" id="text-color" size="10">
        <select id="text-align">
            <option value="left">Align Left</option>
            <option value="center">Align Center</option>
            <option value="right">Align Right</option>
            <option value="justify">Align Justify</option>
          </select>
        <label for="text-stroke-color">Stroke C:</label>
        <input type="color" id="text-stroke-color">
        <label for="text-stroke-width">Stroke W:</label>
        <input type="number" value="1" min="1" max="5" id="text-stroke-width">
        <label for="text-font-size">Font S:</label>
        <input type="number" min="12" max="120" step="1" id="text-font-size">
        <label for="text-line-height">Line H:</label>
        <input type="number" min="0" max="10" step="0.1" id="text-line-height">
        <label for="text-bg-color">BG Color:</label>
        <input type="color" id="text-bg-color" size="10">
        <label for="text-lines-bg-color">BG Text Color:</label>
        <input type="color" id="text-lines-bg-color" size="10">
        <input type='checkbox' name='fonttype' id="text-cmd-bold"> <b>B</b>
        <input type='checkbox' name='fonttype' id="text-cmd-italic"> <em>I</em>
        <input type='checkbox' name='fonttype' id="text-cmd-underline"> Underline
        <input type='checkbox' name='fonttype' id="text-cmd-linethrough"> Linethrough
        <input type='checkbox' name='fonttype' id="text-cmd-overline"> Overline
      </div>
    </div>
  </div>
  <canvas id="c" width="700" height="500"></canvas>
  <script src="fabric/fabric.min.js"></script>
  <script src="javascript.js"></script>
</body>

</html>

【问题讨论】:

    标签: javascript jquery html css fabricjs


    【解决方案1】:

    您可以使用 setBackgroundImage() 方法通过 fabric.js 将背景图像添加到画布。

    document.getElementById(id).addEventListener("change", function(e) {
       var file = e.target.files[0];
       var reader = new FileReader();
       reader.onload = function(f) {
          var data = f.target.result;
          fabric.Image.fromURL(data, function(img) {
             // add background image
             canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas), {
                scaleX: canvas.width / img.width,
                scaleY: canvas.height / img.height
             });
          });
       };
       reader.readAsDataURL(file);
    });
    

    ᴡᴏʀᴋɪɴɢ ᴇxᴀᴍᴘʟᴇ ⧩

    // Add image from local
    var canvas = new fabric.Canvas('c');
    // display/hide text controls
    canvas.on('object:selected', function(e) {
       if (e.target.type === 'i-text') {
          document.getElementById('textControls').hidden = false;
       }
    });
    canvas.on('before:selection:cleared', function(e) {
       if (e.target.type === 'i-text') {
          document.getElementById('textControls').hidden = true;
       }
    });
    document.getElementById('file').addEventListener("change", function(e) {
       var file = e.target.files[0];
       var reader = new FileReader();
       reader.onload = function(f) {
          var data = f.target.result;
          fabric.Image.fromURL(data, function(img) {
             var oImg = img.set({
                left: 0,
                top: 0,
                angle: 0,
                border: '#000',
                stroke: '#F0F0F0', //<-- set this
                strokeWidth: 40 //<-- set this
             }).scale(0.2);
             canvas.add(oImg).renderAll();
             //var a = canvas.setActiveObject(oImg);
             var dataURL = canvas.toDataURL({
                format: 'png',
                quality: 1
             });
          });
       };
       reader.readAsDataURL(file);
    });
    
    
    document.getElementById('file2').addEventListener("change", function(e) {
       var file = e.target.files[0];
       var reader = new FileReader();
       reader.onload = function(f) {
          var data = f.target.result;
          fabric.Image.fromURL(data, function(img) {
             // add background image
             canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas), {
                scaleX: canvas.width / img.width,
                scaleY: canvas.height / img.height
             });
          });
       };
       reader.readAsDataURL(file);
    });
    
    // Delete selected object
    window.deleteObject = function() {
          var activeGroup = canvas.getActiveGroup();
          if (activeGroup) {
             var activeObjects = activeGroup.getObjects();
             for (let i in activeObjects) {
                canvas.remove(activeObjects[i]);
             }
             canvas.discardActiveGroup();
             canvas.renderAll();
          } else canvas.getActiveObject().remove();
       }
       // Refresh page
    function refresh() {
       setTimeout(function() {
          location.reload()
       }, 100);
    }
    // Add text
    function Addtext() {
       canvas.add(new fabric.IText('Tap and Type', {
          left: 50,
          top: 100,
          fontFamily: 'helvetica neue',
          fill: '#000',
          stroke: '#fff',
          strokeWidth: .1,
          fontSize: 45
       }));
    }
    // Edit Text
    document.getElementById('text-color').onchange = function() {
       canvas.getActiveObject().setFill(this.value);
       canvas.renderAll();
    };
    document.getElementById('text-color').onchange = function() {
       canvas.getActiveObject().setFill(this.value);
       canvas.renderAll();
    };
    document.getElementById('text-bg-color').onchange = function() {
       canvas.getActiveObject().setBackgroundColor(this.value);
       canvas.renderAll();
    };
    document.getElementById('text-lines-bg-color').onchange = function() {
       canvas.getActiveObject().setTextBackgroundColor(this.value);
       canvas.renderAll();
    };
    document.getElementById('text-stroke-color').onchange = function() {
       canvas.getActiveObject().setStroke(this.value);
       canvas.renderAll();
    };
    document.getElementById('text-stroke-width').onchange = function() {
       canvas.getActiveObject().setStrokeWidth(this.value);
       canvas.renderAll();
    };
    document.getElementById('font-family').onchange = function() {
       canvas.getActiveObject().setFontFamily(this.value);
       canvas.renderAll();
    };
    document.getElementById('text-font-size').onchange = function() {
       canvas.getActiveObject().setFontSize(this.value);
       canvas.renderAll();
    };
    document.getElementById('text-line-height').onchange = function() {
       canvas.getActiveObject().setLineHeight(this.value);
       canvas.renderAll();
    };
    document.getElementById('text-align').onchange = function() {
       canvas.getActiveObject().setTextAlign(this.value);
       canvas.renderAll();
    };
    radios5 = document.getElementsByName("fonttype"); // wijzig naar button
    for (var i = 0, max = radios5.length; i < max; i++) {
       radios5[i].onclick = function() {
          if (document.getElementById(this.id).checked == true) {
             if (this.id == "text-cmd-bold") {
                canvas.getActiveObject().set("fontWeight", "bold");
             }
             if (this.id == "text-cmd-italic") {
                canvas.getActiveObject().set("fontStyle", "italic");
             }
             if (this.id == "text-cmd-underline") {
                canvas.getActiveObject().set("textDecoration", "underline");
             }
             if (this.id == "text-cmd-linethrough") {
                canvas.getActiveObject().set("textDecoration", "line-through");
             }
             if (this.id == "text-cmd-overline") {
                canvas.getActiveObject().set("textDecoration", "overline");
             }
          } else {
             if (this.id == "text-cmd-bold") {
                canvas.getActiveObject().set("fontWeight", "");
             }
             if (this.id == "text-cmd-italic") {
                canvas.getActiveObject().set("fontStyle", "");
             }
             if (this.id == "text-cmd-underline") {
                canvas.getActiveObject().set("textDecoration", "");
             }
             if (this.id == "text-cmd-linethrough") {
                canvas.getActiveObject().set("textDecoration", "");
             }
             if (this.id == "text-cmd-overline") {
                canvas.getActiveObject().set("textDecoration", "");
             }
          }
          canvas.renderAll();
       }
    }
    // Send selected object to front or back
    var selectedObject;
    canvas.on('object:selected', function(event) {
       selectedObject = event.target;
    });
    var sendSelectedObjectBack = function() {
       canvas.sendToBack(selectedObject);
    }
    var sendSelectedObjectToFront = function() {
          canvas.bringToFront(selectedObject);
       }
       // Download
    var imageSaver = document.getElementById('lnkDownload');
    imageSaver.addEventListener('click', saveImage, false);
    
    function saveImage(e) {
       this.href = canvas.toDataURL({
          format: 'png',
          quality: 0.8
       });
       this.download = 'custom.png'
    }
    // Do some initializing stuff
    fabric.Object.prototype.set({
       transparentCorners: true,
       cornerColor: '#22A7F0',
       borderColor: '#22A7F0',
       cornerSize: 12,
       padding: 5
    });
    body {
       padding: 10px 10px 10px 10px;
       font-family: "HelveticaNeue";
    }
    
    canvas {
       border: 1px solid #bdc3c7;
       margin: 10px 0px 0px 0px;
       /*  background-image: url("images/bg.png"); */
    }
    
    .myFile {
       position: relative;
       overflow: hidden;
       float: left;
       clear: left;
    }
    
    .myFile input[type="file"] {
       display: block;
       position: absolute;
       top: 0;
       right: 0;
       opacity: 0;
       font-size: 30px;
       filter: alpha(opacity=0);
    }
    
    .myFile2 input[type="file"] {
       display: block;
       position: absolute;
       top: 0;
       right: 0;
       opacity: 0;
       font-size: 30px;
       filter: alpha(opacity=0);
    }
    
    .title {
       color: black;
       text-decoration: none;
       margin-bottom: 20px;
       display: block;
    }
    
    hr {
       text-align: left;
       margin: 30px auto 0 0;
       width: 700px;
    }
    
    a:visited {
       text-decoration: none;
       color: #000;
    }
    
    a:active {
       text-decoration: none;
       color: #000;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.0.0-beta.7/fabric.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <label><a style="text-decoration: none;" href="#"><span class="mdi mdi-lightbulb-on-outline">Brand</span></a></label>
    <br>
    <br>
    <label title="Add an image" class="myFile"><span class="mdi mdi-image"> Add Photo</span>&nbsp;
       <input type="file" id="file" />
    </label>
    <label title="Add a background" class="myFile2"><span class="mdi mdi-image"> Add Background</span>&nbsp;
       <input type="file" id="file2" />
    </label>
    <a onclick="Addtext()" title="Add text"><span class="mdi mdi-format-text"> Add Text</span></a>&emsp;
    <a onclick="sendSelectedObjectToFront()" title="Bring selected to front"><span class="mdi mdi-arrange-bring-forward"> Front</span></a>
    <a onclick="sendSelectedObjectBack()" title="Send selected to back"><span class="mdi mdi-arrange-send-backward"> Back</span></a>
    <a onClick="deleteObject()" title="Delete Anything Selected"><span class="mdi mdi-delete"> Delete</span></a>&emsp;
    <a onclick="refresh()" title="Start fresh"><span class="mdi mdi-shredder"> Clear All</span></a>&emsp;
    <a id="lnkDownload" title="Save"><span class="mdi mdi-download"> Save</span></a>
    <div id="textControls" hidden>
       <div id="text-wrapper" data-ng-show="getText()">
          <div id="text-controls">
             <select id="font-family">
                <option value="arial">Arial</option>
                <option value="HelveticaNeue" selected>Helvetica Neue</option>
                <option value="myriad pro">Myriad Pro</option>
                <option value="delicious">Delicious</option>
                <option value="verdana">Verdana</option>
                <option value="georgia">Georgia</option>
                <option value="courier">Courier</option>
                <option value="comic sans ms">Comic Sans MS</option>
                <option value="impact">Impact</option>
                <option value="monaco">Monaco</option>
                <option value="optima">Optima</option>
                <option value="hoefler text">Hoefler Text</option>
                <option value="plaster">Plaster</option>
                <option value="engagement">Engagement</option>
             </select>
             <input type="color" id="text-color" size="10">
             <select id="text-align">
                <option value="left">Align Left</option>
                <option value="center">Align Center</option>
                <option value="right">Align Right</option>
                <option value="justify">Align Justify</option>
             </select>
             <label for="text-stroke-color">Stroke C:</label>
             <input type="color" id="text-stroke-color">
             <label for="text-stroke-width">Stroke W:</label>
             <input type="number" value="1" min="1" max="5" id="text-stroke-width">
             <label for="text-font-size">Font S:</label>
             <input type="number" min="12" max="120" step="1" id="text-font-size">
             <label for="text-line-height">Line H:</label>
             <input type="number" min="0" max="10" step="0.1" id="text-line-height">
             <label for="text-bg-color">BG Color:</label>
             <input type="color" id="text-bg-color" size="10">
             <label for="text-lines-bg-color">BG Text Color:</label>
             <input type="color" id="text-lines-bg-color" size="10">
             <input type='checkbox' name='fonttype' id="text-cmd-bold"> <b>B</b>
             <input type='checkbox' name='fonttype' id="text-cmd-italic"> <em>I</em>
             <input type='checkbox' name='fonttype' id="text-cmd-underline"> Underline
             <input type='checkbox' name='fonttype' id="text-cmd-linethrough"> Linethrough
             <input type='checkbox' name='fonttype' id="text-cmd-overline"> Overline
          </div>
       </div>
    </div>
    <canvas id="c" width="700" height="500"></canvas>

    【讨论】:

    • 嘿ℊααnd!谢谢。这是非常接近的。唯一的问题是,当我将画布作为图像保存到桌面时,不显示背景。
    • 就是这样。谢谢你。
    • 对于 2.0 Fabric 版本,使用画布大小拉伸图像时存在问题,请参阅此问题:stackoverflow.com/questions/47010467/… Credits 转到 @Grunt
    【解决方案2】:

    您也可以使用 setBackgroundColor() 方法将背景图像添加到画布。

    setCanvasImage (canvasImage) {
        self = this;
        if (canvasImage) {
          this.canvas.setBackgroundColor({ source: canvasImage, repeat: 'repeat' }, function () {
            self.canvas.renderAll();
          })
        }
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-07
      • 1970-01-01
      • 2012-01-01
      • 2010-12-29
      • 2020-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多