代码之家  ›  专栏  ›  技术社区  ›  Abilash Erikson

如何在前端拍摄包含用户上传图像的div的截图?

  •  10
  • Abilash Erikson  · 技术社区  · 8 年前

    请查看此代码。在以下代码中,用户可以上传图像,他们可以移动、调整大小、旋转上传的图像等。

    $(function() {
      var inputLocalFont = $("#user_file");
      inputLocalFont.change(previewImages);
    
      function previewImages() {
        var fileList = this.files;
        var anyWindow = window.URL || window.webkitURL;
    
        for (var i = 0; i < fileList.length; i++) {
          var objectUrl = anyWindow.createObjectURL(fileList[i]);
          var $newDiv = $("<div>", {
            class: "img-div"
          });
          var $newImg = $("<img>", {
            src: objectUrl,
            class: "newly-added"
          }).appendTo($newDiv);
          $(".new-multiple").append($newDiv);
          $newDiv.draggable();
          $newDiv.rotatable();
          $newDiv.resizable({
            aspectRatio: true,
            handles: "ne, nw, e, se, sw, w"
          });
          $newDiv.find(".ui-icon").removeClass("ui-icon ui-icon-gripsmall-diagonal-se");
          window.URL.revokeObjectURL(fileList[i]);
        }
        $(".newly-added").on("click", function(e) {
          $(".newly-added").removeClass("img-selected");
          $(this).addClass("img-selected");
          e.stopPropagation()
        });
    
        $(document).on("click", function(e) {
          if ($(e.target).is(".newly-added") === false) {
            $(".newly-added").removeClass("img-selected");
          }
        });
      }
       $(".user_submit").on("click",function(e){
       e.preventDefault();
       html2canvas($('.new-multiple'), {
         allowTaint: true,
    	  onrendered: function(canvas) {
    		document.body.appendChild(canvas);
    		}
    });
      
      
      });
    
    });
    .new-multiple {
      width: 400px !important;
      height: 400px !important;
      background: white;
      border: 2px solid red;
      overflow: hidden;
    }
    
    .img-div {
      width: 200px;
      height: 200px;
    }
    
    .newly-added {
      width: 100%;
      height: 100%;
    }
    
    .img-selected {
      box-shadow: 1px 2px 6px 6px rgb(206, 206, 206);
      border: 2px solid rgb(145, 44, 94);
    }
    
    
    /*
    .ui-resizable-handle.ui-resizable-se.ui-icon.ui-icon-gripsmall-diagonal-se {
      background-color: white;
      border: 1px solid tomato;
    }
    */
    
    .ui-resizable-handle {
      border: 0;
      border-radius: 50%;
      background-color: #00CCff;
      width: 14px;
      height: 14px;
    }
    
    .ui-resizable-nw {
      top: -7px;
      left: -7px;
    }
    
    .ui-resizable-ne {
      top: -7px;
      right: -7px;
    }
    
    .ui-resizable-e {
      top: calc(50% - 7px);
      right: -7px;
    }
    
    .ui-resizable-w {
      top: calc(50% - 7px);
      left: -7px;
    }
    
    .ui-resizable-sw {
      bottom: -7px;
      left: -7px;
    }
    
    .ui-resizable-se {
      right: -7px;
      bottom: -7px;
    }
    
    .ui-resizable-se.ui-icon {
      display: none;
    }
    
    .ui-rotatable-handle {
      background-size: 14px;
      background-repeat: no-repeat;
      background-position: center;
      border: 0;
      border-radius: 50%;
      background-color: #00CCff;
      margin-left: calc(50% - 9px);
      bottom: -5px;
      width: 18px;
      height: 18px;
    }
    <link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet"/>
    <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    <link href="https://cdn.jsdelivr.net/gh/godswearhats/jquery-ui-rotatable@1.1/jquery.ui.rotatable.css" rel="stylesheet"/>
    <script src="https://cdn.jsdelivr.net/gh/godswearhats/jquery-ui-rotatable@1.1/jquery.ui.rotatable.min.js"></script>
     <script src="https://html2canvas.hertzen.com/build/html2canvas.js"></script>
    
    <form method="post" action="">
    
    
    <input name="user_file[]" id="user_file" style="position: relative;overflow: hidden" multiple="" type="file">
    
    <div class="new-multiple"></div>
    <input type="submit" name="submit" class="user_submit" value="submit" />
    </form>

    https://jsfiddle.net/s99kxydw/15/

    我们如何生成这个屏幕截图?

    我们找到了一个解决方案。那就是 html2canvas https://html2canvas.hertzen.com/

    html2canvas不支持css transform 所有物

    有没有其他不使用html2canvas的方法?

    5 回复  |  直到 8 年前
        1
  •  6
  •   user3391232 user3391232    8 年前

    我理解你的问题是什么,因为我用html2canvas做了类似的事情。它的问题。它无法保存所有内容,因此可能不完全准确,例如,它无法进行css文本剪辑。这对我来说很管用(我让它下载了图片,但你也可以很容易地保存它。查看此链接了解如何做到这一点):

    html2canvas($('.classOfElementToSave'), {
          allowTaint: true,
          onrendered: function(canvas) {
            var dataURL = canvas.toDataURL();
            $.ajax({
              type: "POST",
              url: "script.php",
              data: { 
                 imgBase64: dataURL
              }
            }).done(function(o) {
              console.log('saved'); 
              // If you want the file to be visible in the browser 
              // simply return the url previously saved
        });
          }
      });
    

    $img = $_POST['data'];
    $img = str_replace('data:image/png;base64,', '', $img); //Because saved as a data image
    $img = str_replace(' ', '+', $img);
    $fileData = base64_decode($img);
    //saving the image to server
    $fileName = 'image.png';
    file_put_contents($fileName, $fileData);
    
        2
  •  6
  •   ɢʀᴜɴᴛ    8 年前

    html2canvas 支持大多数css属性(基本属性除外),其中之一是 transform 正如你可能已经知道的,还有 解决方法 (使用html2canvas)

    但是,您可以使用名为 FabricJS (移动、调整大小、旋转等) 用户上传的图像 .

    使用这个库最好的地方是,您不需要使用html2canvas或任何其他附加库来截图。您可以直接保存画布 (截图)

    这是一个 basic example

    var canvas = new fabric.Canvas('myCanvas', {
       backgroundColor: 'white'
    });
    
    function renderImage(e) {
       var imgUrl = URL.createObjectURL(e.target.files[0]);
       fabric.Image.fromURL(imgUrl, function(img) {
          // set default props
          img.set({
             width: 150,
             height: 150,
             top: 75,
             left: 75,
             transparentCorners: false
          });
          canvas.add(img);
          canvas.renderAll();
       });
    }
    
    function saveOnPC() {
       var link = document.createElement('a');
       link.href = canvas.toDataURL();
       link.download = 'myImage.png';
       link.click();
    }
    
    function saveOnServer() {
       $.post('https://your-site-name.com/save-image.php', {
          data: canvas.toDataURL()
       }, function() {
          console.log('Image saved on server!');
       });
    
       /* use the following PHP code for 'save-image.php' on server-side
    
       <? php
       $img = $_POST['data'];
       $img = str_replace('data:image/png;base64,', '', $img);
       $img = str_replace(' ', '+', $img);
       $fileData = base64_decode($img);
       $fileName = 'myImage.png';
       file_put_contents($fileName, $fileData);
    	
       */
    }
    canvas{border:1px solid red}input{margin-bottom:6px}button{margin:10px 3px 0 0}
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.19/fabric.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <input type="file" onchange="renderImage(event)">
    <canvas id="myCanvas" width="300" height="300"></canvas>
    <button onclick="saveOnPC()">Save on PC</button>
    <button onclick="saveOnServer()">Save on Server</button>

    要了解有关FabricJS库的更多信息,请参阅它 Official Documentation

        3
  •  3
  •   Twisty    8 年前

    这一半展示了如何捕捉所有各种细节。假设红框是新图像的视口,这将在您进行更改时收集详细信息,以便您可以将其传递给将构建图像的脚本。

    我假设可以捕捉以下细节:

    • 尺寸
    • 位置
    • 旋转

    如果需要,可以删除文件名,让用户指定名称值。

    <form method="post" action="">
      <button id="browse-btn">Browse Images</button>
      <input name="user_file[]" id="user_file" style="display: none; position: relative;overflow: hidden" multiple="" type="file" />
      <div class="new-multiple"></div>
      <button id="submit-btn" type="submit">Submit</button>
      <div class="meta-details">
        <ul>
          <li>
            <label>Name:</label>
            <span></span>
          </li>
          <li>
            <label>Size:</label>
            <span></span>
          </li>
          <li>
            <label>Width:</label>
            <span></span>
          </li>
          <li>
            <label>Height:</label>
            <span></span>
          </li>
          <li>
            <label>Top:</label>
            <span></span>
          </li>
          <li>
            <label>Left:</label>
            <span></span>
          </li>
          <li>
            <label>Rotation:</label>
            <span></span>
          </li>
        </ul>
      </div>
    </form>
    

    form button {
      margin: 3px;
    }
    
    .new-multiple {
      width: 400px !important;
      height: 400px !important;
      background: white;
      border: 2px solid #faa;
      border-radius: 3px;
      overflow: hidden;
    }
    
    .img-div {
      width: 200px;
      height: 200px;
    }
    
    .newly-added {
      width: 100%;
      height: 100%;
    }
    
    .img-selected {
      box-shadow: 1px 2px 6px 6px rgb(206, 206, 206);
      border: 2px solid rgb(145, 44, 94);
    }
    
    .ui-resizable-handle {
      border: 0;
      border-radius: 50%;
      background-color: #00CCff;
      width: 14px;
      height: 14px;
    }
    
    .ui-resizable-nw {
      top: -7px;
      left: -7px;
    }
    
    .ui-resizable-ne {
      top: -7px;
      right: -7px;
    }
    
    .ui-resizable-e {
      top: calc(50% - 7px);
      right: -7px;
    }
    
    .ui-resizable-w {
      top: calc(50% - 7px);
      left: -7px;
    }
    
    .ui-resizable-sw {
      bottom: -7px;
      left: -7px;
    }
    
    .ui-resizable-se {
      right: -7px;
      bottom: -7px;
    }
    
    .ui-resizable-se.ui-icon {
      display: none;
    }
    
    .ui-rotatable-handle {
      background-size: 14px;
      background-repeat: no-repeat;
      background-position: center;
      border: 0;
      border-radius: 50%;
      background-color: #00CCff;
      margin-left: calc(50% - 9px);
      bottom: -5px;
      width: 18px;
      height: 18px;
    }
    
    .meta-details ul {
      padding: 0;
      margin: 0;
      list-style: none;
      font-family: Arial, sans-serif;
      font-size: 9px;
    }
    
    .meta-details ul li label {
      display: inline-block;
      width: 45px;
    }
    

    JavaScript

    $(function() {
      var inputLocalFont = $("#user_file");
      inputLocalFont.change(previewImages);
    
      function humanFileSize(bytes, si) {
        var thresh = si ? 1000 : 1024;
        if (Math.abs(bytes) < thresh) {
          return bytes + ' B';
        }
        var units = si ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
        var u = -1;
        do {
          bytes /= thresh;
          ++u;
        } while (Math.abs(bytes) >= thresh && u < units.length - 1);
        return bytes.toFixed(1) + ' ' + units[u];
      }
    
      function logMeta(d) {
        var $m = $(".meta-details ul li span");
        $m.eq(0).html(d.name);
        $m.eq(1).html(humanFileSize(d.size));
        $m.eq(2).html(d.width + " px");
        $m.eq(3).html(d.height + " px");
        $m.eq(4).html(d.top + " px");
        $m.eq(5).html(d.left + " px");
        $m.eq(6).html(d.rotateDeg + " &deg;");
      }
    
      function previewImages() {
        var fileList = this.files;
        var fileMeta = [];
        $.each(fileList, function(key, val) {
          fileMeta[key] = {
            name: val.name,
            size: val.size,
            modified: val.lastModified
          };
        });
        var anyWindow = window.URL || window.webkitURL;
    
        for (var i = 0; i < fileList.length; i++) {
          var $list = fileList[i];
          var $meta = fileMeta[i];
          var objectUrl = anyWindow.createObjectURL(fileList[i]);
          var $newDiv = $("<div>", {
            class: "img-div"
          });
          var $newImg = $("<img>", {
            src: objectUrl,
            class: "newly-added"
          }).appendTo($newDiv);
          $meta['width'] = $newImg.width();
          $meta['height'] = $newImg.height();
          $meta['rotateDeg'] = 0.000;
          $meta['top'] = $newImg.position().top;
          $meta['left'] = $newImg.position().left;
          $(".new-multiple").append($newDiv);
          $newDiv.draggable({
            drag: function(e, ui) {
              $meta['top'] = ui.position.top;
              $meta['left'] = ui.position.left;
              logMeta($meta);
              $newImg.data("meta", $meta);
            }
          });
          $newDiv.rotatable({
            rotate: function(e, ui) {
              $meta['rotateDeg'] = Math.round(ui.angle.degrees * 10000) / 10000;
              $meta['rotateRad'] = ui.angle.current;
              logMeta($meta);
              $newImg.data("meta", $meta);
            }
          });
          $newDiv.resizable({
            aspectRatio: true,
            handles: "ne, nw, e, se, sw, w",
            resize: function(e, ui) {
              $meta['width'] = ui.size.width;
              $meta['height'] = ui.size.height;
              logMeta($meta);
              $newImg.data("meta", $meta);
            }
          });
          $newDiv.find(".ui-icon").removeClass("ui-icon ui-icon-gripsmall-diagonal-se");
          window.URL.revokeObjectURL(fileList[i]);
          console.log($meta);
          logMeta($meta);
          $newImg.data("meta", $meta);
        }
        $(".newly-added").on("click", function(e) {
          $(".newly-added").removeClass("img-selected");
          $(this).addClass("img-selected");
          e.stopPropagation();
        });
    
        $(document).on("click", function(e) {
          if ($(e.target).is(".newly-added") === false) {
            $(".newly-added").removeClass("img-selected");
          }
        });
      }
      $("button").button();
      $("#browse-btn").click(function(e) {
        e.preventDefault();
        $("#user_file").trigger("click");
      });
      $("#browse-btn").click(function(e) {
        e.preventDefault();
        $(this).parent().submit();
      });
      $("form").submit(function(e) {
        e.preventDefault();
        console.log("Prepared Meta Data:");
        $(".newly-added").each(function() {
          console.log($(this).data("meta"));
        });
        // AJAX Post Code will be entered here
      });
    });
    

    @mpen converting file size in bytes to human-readable string 用于文件大小转换函数。

    您可以看到,我们创建了一个数组来存储与文件关联的相应细节。当拖动、调整或旋转项目时,该选项会更新。提交表单时,您可以将这些详细信息与原始图像一起提交。所以至少你的用户界面现在已经构建好了。

    Image Processing 对于PHP。查看要使用的脚本,然后从后端脚本开始。

        4
  •  2
  •   guest271314    8 年前

    遵循@ValfarDeveloper,您可以分配 .src <img> data URI 而不是 Blob URL 并设置的当前HTML ".new-multiple" <foreignObject> 中的元素 <svg> 一串

    $(function() {
      var inputLocalFont = $("#user_file");
      inputLocalFont.change(previewImages);
    
      async function previewImages() {
        var fileList = this.files;
        var anyWindow = window.URL || window.webkitURL;
    
        for (var i = 0; i < fileList.length; i++) {
          var objectUrl = await new Promise(resolve => {
            var reader = new FileReader;
            reader.onload = e => resolve(reader.result);
            reader.readAsDataURL(fileList[i]);
          });
          var $newDiv = $("<div>", {
            class: "img-div"
          });
          var $newImg = $("<img>", {
            src: objectUrl,
            class: "newly-added"
          }).appendTo($newDiv);
          $(".new-multiple").append($newDiv);
          $newDiv.draggable();
          $newDiv.rotatable();
          $newDiv.resizable({
            aspectRatio: true,
            handles: "ne, nw, e, se, sw, w"
          });
          $newDiv.find(".ui-icon").removeClass("ui-icon ui-icon-gripsmall-diagonal-se");
        }
        $(".newly-added").on("click", function(e) {
          $(".newly-added").removeClass("img-selected");
          $(this).addClass("img-selected");
          e.stopPropagation()
        });
    
        $(document).on("click", function(e) {
          if ($(e.target).is(".newly-added") === false) {
            $(".newly-added").removeClass("img-selected");
          }
        });
      }
       $(".user_submit").on("click",function(e){
       e.preventDefault();
       let html = $(".new-multiple").html();
       let svg = `<?xml version="1.0" standalone="yes"?>
    <svg xmlns="http://www.w3.org/2000/svg" width="400px" height="400px" viewBox="0 0 400 300">
        <foreignObject width="400px" height="300px" 
         requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility">
          <html xmlns="http://www.w3.org/1999/xhtml">
          ${html}
          </html>
          </foreignObject>
    </svg>`;
      
        $("body").append(svg);
      
      });
    
    });
    .new-multiple {
      width: 400px !important;
      height: 400px !important;
      background: white;
      border: 2px solid red;
      overflow: hidden;
    }
    
    .img-div {
      width: 200px;
      height: 200px;
    }
    
    .newly-added {
      width: 100%;
      height: 100%;
    }
    
    .img-selected {
      box-shadow: 1px 2px 6px 6px rgb(206, 206, 206);
      border: 2px solid rgb(145, 44, 94);
    }
    
    
    /*
    .ui-resizable-handle.ui-resizable-se.ui-icon.ui-icon-gripsmall-diagonal-se {
      background-color: white;
      border: 1px solid tomato;
    }
    */
    
    .ui-resizable-handle {
      border: 0;
      border-radius: 50%;
      background-color: #00CCff;
      width: 14px;
      height: 14px;
    }
    
    .ui-resizable-nw {
      top: -7px;
      left: -7px;
    }
    
    .ui-resizable-ne {
      top: -7px;
      right: -7px;
    }
    
    .ui-resizable-e {
      top: calc(50% - 7px);
      right: -7px;
    }
    
    .ui-resizable-w {
      top: calc(50% - 7px);
      left: -7px;
    }
    
    .ui-resizable-sw {
      bottom: -7px;
      left: -7px;
    }
    
    .ui-resizable-se {
      right: -7px;
      bottom: -7px;
    }
    
    .ui-resizable-se.ui-icon {
      display: none;
    }
    
    .ui-rotatable-handle {
      background-size: 14px;
      background-repeat: no-repeat;
      background-position: center;
      border: 0;
      border-radius: 50%;
      background-color: #00CCff;
      margin-left: calc(50% - 9px);
      bottom: -5px;
      width: 18px;
      height: 18px;
    }
    <link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet"/>
    <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    <link href="https://cdn.jsdelivr.net/gh/godswearhats/jquery-ui-rotatable@1.1/jquery.ui.rotatable.css" rel="stylesheet"/>
    <script src="https://cdn.jsdelivr.net/gh/godswearhats/jquery-ui-rotatable@1.1/jquery.ui.rotatable.min.js"></script>
     <script src="https://html2canvas.hertzen.com/build/html2canvas.js"></script>
    
    <form method="post" action="">
    
    
    <input name="user_file[]" id="user_file" style="position: relative;overflow: hidden" multiple="" type="file">
    
    <div class="new-multiple"></div>
    <input type="submit" name="submit" class="user_submit" value="submit" />
    </form>
        5
  •  2
  •   Valfar Developer    8 年前

    我将引用它:

    你可以在Github上找到这个项目,在那里他们解释了如何使用它:

    https://github.com/cburgmer/rasterizeHTML.js

    推荐文章