Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add background image with fabric.js

I'm able to add images by using an input type="file" id="file" however would like to be able upload an image that can be moved and stay behind all else as a background image. Right now I can add something and send it to the back but moving it is difficult because the controls run off the canvas. Any help would be greatly appreciated—thanks in advance.

// 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>
like image 245
anonymoose Avatar asked May 16 '17 19:05

anonymoose


People also ask

How do you clean fabric canvas?

Normally canvas. loadFromJSON() clears the whole canvas before loading new objects. Otherwise you can run canvas. clear(); .

How does fabric JS work?

Fabric. js is based on HTML5 canvas, so just put a canvas object into an HTML file, with an id, and that's it. In the controller's AfterContentInit lifecycle hook (so the canvas was rendered inside the nice wrapper): this.


2 Answers

You can use the setBackgroundImage() method to add a background image to the canvas with 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>
like image 142
ɢʀᴜɴᴛ Avatar answered Sep 19 '22 09:09

ɢʀᴜɴᴛ


You can use the setBackgroundColor() method to add a background image to the canvas too.

setCanvasImage (canvasImage) {
    self = this;
    if (canvasImage) {
      this.canvas.setBackgroundColor({ source: canvasImage, repeat: 'repeat' }, function () {
        self.canvas.renderAll();
      })
    }
  }
like image 26
ouzza brahim Avatar answered Sep 20 '22 09:09

ouzza brahim