Как я могу обрезать картинку и добавить водяной знак?

#javascript #jquery

#javascript #jquery

Вопрос:

Есть идеи, как обрезать созданное изображение и добавить водяной знак?

изображение должно быть квадратным (600 x 600 пикселей), обрезанным посередине, и я должен добавить к нему водяной знак.

Я попробовал этот плагин jqueryhttps://github.com/lelinhtinh/watermark но не работает.

если предварительный просмотр ниже не работает, вы можете посмотреть демонстрацию здесьhttps://jsfiddle.net/y9rhwvgn

любые предложения приветствуются 🙂

 // References to all the element we will need.
var video = document.querySelector('#camera-stream'),
    image = document.querySelector('#snap'),
    start_camera = document.querySelector('#start-camera'),
    controls = document.querySelector('.controls'),
    take_photo_btn = document.querySelector('#take-photo'),
    delete_photo_btn = document.querySelector('#delete-photo'),
    download_photo_btn = document.querySelector('#download-photo'),
    error_message = document.querySelector('#error-message');


// The getUserMedia interface is used for handling camera input.
// Some browsers need a prefix so here we're covering all the options
navigator.getMedia = ( navigator.getUserMedia ||
                      navigator.webkitGetUserMedia ||
                      navigator.mozGetUserMedia ||
                      navigator.msGetUserMedia);


if(!navigator.getMedia){
  displayErrorMessage("Your browser doesn't have support for the navigator.getUserMedia interface.");
}
else{

  // Request the camera.
  navigator.getMedia(
    {
      video: true
    },
    // Success Callback
    function(stream){

      // Create an object URL for the video stream and
      // set it as src of our HTLM video element.
       video.srcObject=stream;

      // Play the video element to start the stream.
      video.play();
      video.onplay = function() {
        showVideo();
      };

    },
    // Error Callback
    function(err){
      displayErrorMessage("There was an error with accessing the camera stream: "   err.name, err);
    }
  );

}



// Mobile browsers cannot play video without user input,
// so here we're using a button to start it manually.
start_camera.addEventListener("click", function(e){

  e.preventDefault();

  // Start video playback manually.
  video.play();
  showVideo();

});


take_photo_btn.addEventListener("click", function(e){

  e.preventDefault();

  var snap = takeSnapshot();

  // Show image. 
  image.setAttribute('src', snap);
  image.classList.add("visible");

  // Enable delete and save buttons
  delete_photo_btn.classList.remove("disabled");
  download_photo_btn.classList.remove("disabled");

  // Set the href attribute of the download button to the snap url.
  download_photo_btn.href = snap;

  // Pause video playback of stream.
  video.pause();

});


delete_photo_btn.addEventListener("click", function(e){

  e.preventDefault();

  // Hide image.
  image.setAttribute('src', "");
  image.classList.remove("visible");

  // Disable delete and save buttons
  delete_photo_btn.classList.add("disabled");
  download_photo_btn.classList.add("disabled");

  // Resume playback of stream.
  video.play();

});



function showVideo(){
  // Display the video stream and the controls.

  hideUI();
  video.classList.add("visible");
  controls.classList.add("visible");
}


function takeSnapshot(){
  // Here we're using a trick that involves a hidden canvas element.  

  var hidden_canvas = document.querySelector('canvas'),
      context = hidden_canvas.getContext('2d');

  var width = video.videoWidth,
      height = video.videoHeight;

  if (width amp;amp; height) {

    // Setup a canvas with the same dimensions as the video.
    hidden_canvas.width = width;
    hidden_canvas.height = height;

    // Make a copy of the current frame in the video on the canvas.
    context.drawImage(video, 0, 0, width, height);

    // Turn the canvas image into a dataURL that can be used as a src for our photo.
    return hidden_canvas.toDataURL('image/png');
  }
}


function displayErrorMessage(error_msg, error){
  error = error || "";
  if(error){
    console.log(error);
  }

  error_message.innerText = error_msg;

  hideUI();
  error_message.classList.add("visible");
}


function hideUI(){
  // Helper function for clearing the app UI.

  controls.classList.remove("visible");
  start_camera.classList.remove("visible");
  video.classList.remove("visible");
  snap.classList.remove("visible");
  error_message.classList.remove("visible");
}  
 @import url('https://fonts.googleapis.com/css?family=Open Sans:400,700');
@import url('https://fonts.googleapis.com/icon?family=Material Icons');

*{
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html{
    background-color: #fff;
    font:normal 16px/1.5 sans-serif;
    color: #333;
}

h3{
    font: normal 32px/1.5 'Open Sans', sans-serif;
    color: #2c3e50;
    margin: 50px 0;
    text-align: center;
}


.container{
    max-width: 1000px;
    margin: 50px auto;
    padding: 20px;
    background-color: #efefef;
}

.app{
    width: 100%;
    position: relative;
}

.app #start-camera{
    display: none;
    border-radius: 3px;
    max-width: 400px;
    color: #fff;
    background-color: #448AFF;
    text-decoration: none;
    padding: 15px;
    opacity: 0.8;
    margin: 50px auto;
    text-align: center;
}

.app video#camera-stream{
    display: none;
    width: 100%;
}

.app img#snap{
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    z-index: 10;
    display: none;
}

.app #error-message{
    width: 100%;
    background-color: #ccc;
    color: #9b9b9b;
    font-size: 28px;
    padding: 200px 100px;
    text-align: center;
    display: none;
}

.app .controls{
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 20;

    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    padding: 30px;
    display: none;
}

.app .controls a{
    border-radius: 50%;
    color: #fff;
    background-color: #111;
    text-decoration: none;
    padding: 15px;
    line-height: 0;
    opacity: 0.7;
    outline: none;
    -webkit-tap-highlight-color: transparent;
}

.app .controls a:hover{
    opacity: 1;
}

.app .controls a.disabled{
    background-color: #555;
    opacity: 0.5;
    cursor: defau<
    pointer-events: none;
}

.app .controls a.disabled:hover{
    opacity: 0.5;
}

.app .controls a i{
    font-size: 18px;
}

.app .controls #take-photo i{
    font-size: 32px;
}

.app canvas{
    display: none;
}



.app video#camera-stream.visible,
.app img#snap.visible,
.app #error-message.visible
{
    display: block;
}

.app .controls.visible{
    display: flex;
}



@media(max-width: 1000px){
    .container{
        margin: 40px;
    }

    .app #start-camera.visible{
        display: block;
    }

    .app .controls a i{
        font-size: 16px;
    }

    .app .controls #take-photo i{
        font-size: 24px;
    }
}


@media(max-width: 600px){
    .container{
        margin: 10px;
    }

    .app #error-message{
        padding: 80px 50px;
        font-size: 18px;
    }

    .app .controls a i{
        font-size: 12px;
    }

    .app .controls #take-photo i{
        font-size: 18px;
    }
}  
 <h3>Demo: Take a Selfie</h3>

<div class="container">

  <div class="app">

    <a href="#" id="start-camera" class="visible">Touch here to start the app.</a>
    <video id="camera-stream"></video>
    <img id="snap">

    <p id="error-message"></p>

    <div class="controls">
      <a href="#" id="delete-photo" title="Delete Photo" class="disabled"><i class="material-icons">delete</i></a>
      <a href="#" id="take-photo" title="Take Photo"><i class="material-icons">camera_alt</i></a>
      <a href="#" id="download-photo" download="selfie.png" title="Save Photo" class="disabled"><i class="material-icons">file_download</i></a>  
    </div>

    <!-- Hidden canvas element. Used for taking snapshot of video. -->
    <canvas></canvas>

  </div>

</div>  

Ответ №1:

У меня была готова пара функций для чего-то, над чем я ранее работал. Эти функции масштабируют ваше изображение так, чтобы оно либо помещалось внутри указанных размеров, либо заполняло указанные размеры.

 var cat_img = 'https://i.chzbgr.com/maxW500/1691290368/h07F7F378/';

(async function() {

  // option one
  var fit = await scaleAndFitImage(cat_img, 600, 600);

  // option two
  var cov = await scaleAndCoverImage(cat_img, 600, 600);

  document.body.innerHTML = `
<h3>option 1: fit</h3>
<img src="${fit}" style='border:1px solid black'>
<h3>option 2: scale</h3>
<img src="${cov}" style='border:1px solid black'>
`;


})();


function loadImage(src) {
  return new Promise((r, e) => {
    var img = new Image();
    img.crossOrigin = "anonymous";
    img.onload = () => r(img);
    img.onerror = e;
    img.src = src;
  });
}

async function scaleAndFitImage(src, w, h) {
  var img = await loadImage(src);
  var canvas = document.createElement('canvas');
  canvas.width = w;
  canvas.height = h;
  var ctx = canvas.getContext('2d');
  var scale = Math.min(canvas.width / img.width, canvas.height / img.height);
  var x = (canvas.width / 2) - (img.width / 2) * scale;
  var y = (canvas.height / 2) - (img.height / 2) * scale;
  ctx.drawImage(img, x, y, img.width * scale, img.height * scale);
  return canvas.toDataURL();
}

async function scaleAndCoverImage(src, w, h) {
  var img = await loadImage(src);
  var canvas = document.createElement('canvas');
  canvas.width = w;
  canvas.height = h;
  var ctx = canvas.getContext('2d');
  var x = y = 0,
    offsetX = 0.5,
    offsetY = 0.5;
  var iw = img.width,
    ih = img.height,
    r = Math.min(w / iw, h / ih),
    nw = iw * r, // new prop. width
    nh = ih * r, // new prop. height
    cx, cy, cw, ch, ar = 1;
  if (nw < w) ar = w / nw;
  if (Math.abs(ar - 1) < 1e-14 amp;amp; nh < h) ar = h / nh; // updated
  nw *= ar;
  nh *= ar;
  cw = iw / (nw / w);
  ch = ih / (nh / h);
  cx = (iw - cw) * offsetX;
  cy = (ih - ch) * offsetY;
  if (cx < 0) cx = 0;
  if (cy < 0) cy = 0;
  if (cw > iw) cw = iw;
  if (ch > ih) ch = ih;
  ctx.drawImage(img, cx, cy, cw, ch, x, y, w, h);
  return canvas.toDataURL();
}