【问题标题】:Trying to compress image using Canvas but JPG or PNG is returning a black image or transparent/empty image尝试使用 Canvas 压缩图像,但 JPG 或 PNG 返回黑色图像或透明/空图像
【发布时间】:2021-03-25 20:44:06
【问题描述】:

我正在尝试在上传之前压缩图像。

点击浏览按钮,选择图片并在 onChange 中调用onFileSelect 函数。

这里我面临 2 个问题

  1. 无法获取 img 的宽度和高度,不知道为什么总是返回零
  2. 最终输出dataurl 是一串字符,但加载时JPG 图像将为黑色图像,而PNG 则为空透明框/图像

尝试了多种方法,但都没有成功。

下面是代码

//HTML

<input type="file" accept=".png,.jpg,.jpeg"  onChange=this.onFileSelect.bind(this)/>

//JS

onFileSelect(evt){
        var filesArr = evt.target.files;
        var reader = new FileReader();
        if(filesArr === undefined || filesArr.length === 0)return;
        var img = document.createElement("img");
        reader.onload = function (e) {
            img.src = e.target.result;

            var canvas = document.createElement("canvas");
            //var ctx = canvas.getContext("2d");
            //ctx.drawImage(img, 0, 0);

            var MAX_WIDTH = 400;
            var MAX_HEIGHT = 400;
            var width = img.width?img.width:MAX_WIDTH;//not getting img width so ternary operator
            var height = img.height?img.height:MAX_HEIGHT;//not getting img height so ternary operator

            if (width > height) {
                if (width > MAX_WIDTH) {
                    height *= MAX_WIDTH / width;
                    width = MAX_WIDTH;
                }
            } else {
                if (height > MAX_HEIGHT) {
                    width *= MAX_HEIGHT / height;
                    height = MAX_HEIGHT;
                }
            }
            canvas.width = width;
            canvas.height = height;
            var ctx = canvas.getContext("2d");
            ctx.drawImage(img, 0, 0, width, height);

            var dataurl = canvas.toDataURL(filesArr[0].type);
            this.setState({
                imagePath: dataurl,
                showImageEditor:true,
            })
        }
        reader.readAsDataURL(filesArr[0]);
    }

【问题讨论】:

    标签: javascript html reactjs file-upload html5-canvas


    【解决方案1】:

    你必须在获得宽度之前渲染 img

    import React, { Component } from 'react'
    
    export default class App extends Component {
      constructor() {
        super()
        this.state = {
          imagePath: '',
          showImageEditor: false,
        }
        this.onFileSelect = this.onFileSelect.bind(this)
      }
      onFileSelect(evt) {
        var filesArr = evt.target.files
        console.log('filesArr', filesArr)
        let self = this
        var reader = new FileReader()
        if (filesArr === undefined || filesArr.length === 0) return
        var img = document.createElement('img')
        reader.onload = function (e) {
          img.src = e.target.result
          var canvas = document.createElement('canvas')
          //var ctx = canvas.getContext("2d");
          //ctx.drawImage(img, 0, 0);
          img.onload = function (i) {
            
            console.log('img', img.width)
            var MAX_WIDTH = 400
            var MAX_HEIGHT = 400
            var width = img.width ? img.width : MAX_WIDTH //not getting img width so ternary operator
            var height = img.height ? img.height : MAX_HEIGHT //not getting img height so ternary operator
    
            if (width > height) {
              if (width > MAX_WIDTH) {
                height *= MAX_WIDTH / width
                width = MAX_WIDTH
              }
            } else {
              if (height > MAX_HEIGHT) {
                width *= MAX_HEIGHT / height
                height = MAX_HEIGHT
              }
            }
            canvas.width = width
            canvas.height = height
            var ctx = canvas.getContext('2d')
            ctx.drawImage(img, 0, 0, width, height)
    
            var dataurl = canvas.toDataURL(filesArr[0].type)
            self.setState({
              imagePath: dataurl,
              showImageEditor: true,
            })
          }
        }
        reader.readAsDataURL(filesArr[0])
      }
      render() {
        const {imagePath}=this.state
        return (
          <div>
            <input
              type='file'
              accept='.png,.jpg,.jpeg'
              onChange={this.onFileSelect}
            />
            {this.state.imagePath ? (
              <img src={this.state.imagePath} alt='' />
            ) : null}
          </div>
        )
      }
    }
    
    

    【讨论】:

    • 非常感谢...!!! @剑道。 img.onload 函数是诀窍。再次感谢
    猜你喜欢
    • 1970-01-01
    • 2013-11-18
    • 2021-08-30
    • 2013-03-17
    • 1970-01-01
    • 1970-01-01
    • 2018-10-09
    • 2013-01-24
    • 1970-01-01
    相关资源
    最近更新 更多