Skip to main content

Canvas Watermark — Add Text Watermark to Images with JavaScript

Add a repeating diagonal watermark to any image. Type custom text, adjust opacity and font size, then export as PNG.

Instructions: Edit the text field, adjust sliders, click Export to download.

import Konva from 'konva';

var width = window.innerWidth;
var height = window.innerHeight;

var stage = new Konva.Stage({
  container: 'container',
  width: width,
  height: height,
});

var layer = new Konva.Layer();
stage.add(layer);

var container = document.getElementById('container');

var controls = document.createElement('div');
controls.style.cssText = 'display:flex;gap:8px;align-items:center;margin-bottom:6px;flex-wrap:wrap;font:12px Arial,sans-serif;';

controls.appendChild(document.createTextNode('Text:'));
var textInput = document.createElement('input');
textInput.type = 'text';
textInput.value = 'SAMPLE';
textInput.style.cssText = 'padding:3px 5px;width:90px;font-size:12px;';
controls.appendChild(textInput);

var opacityLabel = document.createElement('label');
opacityLabel.style.cssText = 'display:flex;align-items:center;gap:4px;';
opacityLabel.appendChild(document.createTextNode('Opacity:'));
var opacitySlider = document.createElement('input');
opacitySlider.type = 'range';
opacitySlider.min = '0.05';
opacitySlider.max = '1';
opacitySlider.step = '0.05';
opacitySlider.value = '0.3';
opacitySlider.style.width = '70px';
opacityLabel.appendChild(opacitySlider);
var opacityVal = document.createElement('span');
opacityVal.textContent = '0.3';
opacityVal.style.minWidth = '24px';
opacityLabel.appendChild(opacityVal);
controls.appendChild(opacityLabel);

var sizeLabel = document.createElement('label');
sizeLabel.style.cssText = 'display:flex;align-items:center;gap:4px;';
sizeLabel.appendChild(document.createTextNode('Size:'));
var sizeSlider = document.createElement('input');
sizeSlider.type = 'range';
sizeSlider.min = '14';
sizeSlider.max = '60';
sizeSlider.step = '2';
sizeSlider.value = '28';
sizeSlider.style.width = '70px';
sizeLabel.appendChild(sizeSlider);
var sizeVal = document.createElement('span');
sizeVal.textContent = '28';
sizeVal.style.minWidth = '20px';
sizeLabel.appendChild(sizeVal);
controls.appendChild(sizeLabel);

var exportBtn = document.createElement('button');
exportBtn.textContent = 'Export PNG';
exportBtn.style.cssText = 'padding:4px 10px;cursor:pointer;font-size:12px;background:#333;color:white;border:none;border-radius:3px;';
controls.appendChild(exportBtn);

container.parentNode.insertBefore(controls, container);

var watermarkGroup = new Konva.Group();

var imageObj = new Image();
imageObj.onload = function() {
  var bgImage = new Konva.Image({
    image: imageObj,
    width: width,
    height: height,
  });
  layer.add(bgImage);
  layer.add(watermarkGroup);
  drawWatermarks();
};
imageObj.src = 'https://konvajs.org/assets/landscape.jpg';

function drawWatermarks() {
  watermarkGroup.destroyChildren();
  var text = textInput.value || 'SAMPLE';
  var opacity = parseFloat(opacitySlider.value);
  var size = parseInt(sizeSlider.value);
  for (var x = -width; x < width * 2; x += 180) {
    for (var y = -height; y < height * 2; y += 120) {
      watermarkGroup.add(new Konva.Text({
        x: x, y: y,
        text: text,
        fontSize: size,
        fontFamily: 'Arial',
        fill: 'white',
        opacity: opacity,
        rotation: -30,
      }));
    }
  }
  layer.draw();
}

textInput.addEventListener('input', drawWatermarks);
opacitySlider.addEventListener('input', function() {
  opacityVal.textContent = parseFloat(this.value).toFixed(2);
  drawWatermarks();
});
sizeSlider.addEventListener('input', function() {
  sizeVal.textContent = this.value;
  drawWatermarks();
});
exportBtn.addEventListener('click', function() {
  var link = document.createElement('a');
  link.href = stage.toDataURL({ pixelRatio: 2 });
  link.download = 'watermarked.png';
  link.click();
});