JS实现 带有话题的文本编辑 + 图片编辑(下)

Posted 银翘解毒片

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS实现 带有话题的文本编辑 + 图片编辑(下)相关的知识,希望对你有一定的参考价值。

 

本篇主要讲述九宫格上传图片

图片编辑实现效果:

 

 

 图片编辑实现原理:

  1. 实现九宫格编辑图片可以做成一个组件,使用原生的图片上传方式通过 input 标签上传图片
  2. 一般图片都挺大,避免用户等待时间过长,使用 canvas 将上传的图片进行压缩
  3. 每次成功上传一张图片 && 图片总量 < 9 就在图片数组后push 一个待编辑图片
  4. 由于上传图片的接口需要formData 格式的文件,就需要将压缩后的base64格式的图片 通过dataURLtoBlob blobToFile 这两个函数转换成file文件,此方法不存在浏览器不兼容问题

 

子组件封装:

<template>
  <div class="addImg_wrap">
    <div class="occupy_img" v-if="!info.imgUrl">
      <img
        src="//nkb-yunpan.oss-cn-beijing.aliyuncs.com/d6de603efa86935328b439f276339c2b.png"
        alt
        @click.self.prevent="addImgEvent"
        class="img1"
      />
      <input
        class="file"
        type="file"
        id="add_input2"
        accept="image/*"
        ref="avatarInput"
        @change="changeImage($event)"
      />
    </div>
    <div class="real_img" v-if="info.imgUrl">
      <img :src="info.imgUrl" alt class="img2" />
      <img
        src="https://nkb-yunpan.oss-cn-beijing.aliyuncs.com/1595a0b56803644173f839f27655754b.png"
        alt
        class="close"
        @click.self.prevent="closeEvent(index)"
      />
    </div>
  </div>
</template>

<script>
export default {
  props: {
    info: {
      type: Object,
      default: null
    },
    index: {
      type: Number,
      default: null
    },
    isLoading: {
      type: Boolean,
      default: null
    },
  },
  data() {
    return {};
  },
  methods: {
    addImgEvent() {
      this.$refs.avatarInput.click();
    },

    changeImage(e) {
      const self = this;
      let imgFile = "";
      let file = e.target.files[0];
      let filename = file.name;
      if (file) {
        let reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = function() {
          // 这里的this 指向reader
          let pic = new Image();
          pic.src = this.result;
          pic.onload = function() {
            var bitmap = new Image();
            bitmap.src = self.compress(pic);
            self.dataUrl = bitmap.src
          };
        };

        // 不加定时器获取不到dataurl
        setTimeout(() => {
          console.log(\'dataUrl\');
          console.log(self.dataUrl);
          let blob = self.dataURLtoBlob(self.dataUrl);
          imgFile = self.blobToFile(blob, filename);
          let data = new FormData();
          data.append("file", imgFile, filename);
          self.getImgUrl(data);
        }, 500);
      }
    },

    // 先将base64转换成blob,再将blob转换成file文件,此方法不存在浏览器不兼容问题
    dataURLtoBlob(dataUrl) {
      var arr = dataUrl.split(","),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new Blob([u8arr], { type: mime });
    },

    blobToFile(theBlob, fileName) {
      theBlob.lastModifiedDate = new Date();
      theBlob.name = fileName;
      return theBlob;
    },

    //压缩图片
    compress(img) {
      let canvas = document.createElement("canvas");
      let ctx = canvas.getContext("2d");
      let width = img.width;
      let height = img.height;
      canvas.width = width;
      canvas.height = height;
      ctx.drawImage(img, 0, 0, width, height);
      //进行压缩
      var ndata = canvas.toDataURL("image/jpeg", 0.5);
      // console.log("已压缩");
      return ndata;
    },

    closeEvent(index) {
      this.$emit("imgDel", index);
    },

    async getImgUrl(data) {
      this.$emit("loadingEvent", true);
      const res = await this.fetch.post("Upload/UploadImage",data, "post",);
      if (res && res.success) {
        // Toast("上传成功");
        this.$emit("imgAdd", { imgUrl: res.result.path, index: this.index,isLoading:false });
      }
    }
  }
};
</script>

<style lang="less" scoped>
.addImg_wrap {
  width: 31%;
  margin-right: 3%;
  margin-bottom: 4%;
  &:nth-child(3n) {
    margin-right: 0;
  }
  .occupy_img,
  .real_img {
    width: 100%;
    height: 200px;
    position: relative;
    .img1 {
      width: 100%;
      height: 206px;
      box-sizing: border-box;
      // border: 2px dashed #888888;
    }
    .img2 {
      box-sizing: border-box;
      width: 100%;
      height: 206px;
      border: 0;
    }
  }
  .close {
    position: absolute;
    width: 32px;
    height: 32px;
    top: 0;
    right: 0;
    z-index: 9;
  }
  .file {
    opacity: 0;
    width: 1px;
    height: 1px;
  }
}
</style>
View Code

 

父组件调用:

<template>
  <div class="nineImgs_wrap">
    <div class="edit_img">
      <addImgComponent
        v-for="(item,index) in imgList"
        :key="index"
        :info.sync="item"
        @imgDel="imgDel"
        @imgAdd="imgAdd"
        @loadingEvent="loadingEvent"
        :index="index"
        :isLoading="isLoading"
      ></addImgComponent>
    </div>

     <div class="loading" v-if="isLoading">
      <van-loading type="spinner" size="30px" vertical></van-loading>
    </div>
  </div>
</template>

<script>
import addImgComponent from "@/components/addImg.vue";
export default {
  name: "nineImgs",
  components: {
    addImgComponent
  },
  data() {
    return {
      imgList: [
        {
          imgUrl: ""
        }
      ],
      isLoading: false
    };
  },
  methods: {
    loadingEvent(val){
      this.isLoading = val
    },
    imgAdd(val) {
      this.isLoading = val.isLoading
      this.imgList.forEach((v, i) => {
        if (i === val.index) {
          v.imgUrl = val.imgUrl;
        }
      });
      const a = {
        imgUrl: null
      };
      this.imgList.push(a);
      
    },
    imgDel(d) {
      this.imgList.forEach((v, i) => {
        if (i === d) {
          this.imgList.splice(i, 1);
        }
      });
    }
  }
};
</script>

<style lang="less" scoped>
.nineImgs_wrap {
  width: 100%;
  padding: 30px;
  font-size: 18px;
  .edit_img {
    display: flex;
    flex-wrap: wrap;
    margin-top: 20px;
    .real_img,
    .occupy_img .img1 {
      height: 200px !important;
    }
  }
  .loading{
    width: 100%;
  }
}
</style>
View Code

 

 

分享一刻:

浏览器禁用三方 Cookie 的分析

Safari 浏览器开始完全禁用第三方 Cookie,本文分析了有何影响,以及如何在没有 Cookie 的情况下,获取浏览器的指纹。

以上是关于JS实现 带有话题的文本编辑 + 图片编辑(下)的主要内容,如果未能解决你的问题,请参考以下文章

超文本编辑器如何上传图片?

带有角度 JS 的可编辑文本就像普通链接一样

KindEditor富文本框编辑器上传图片功能实现,基于java项目

对于富文本编辑器中使用lazyload图片懒加载

Editor富文本编辑器配置不含图片上传

laravel富文本编辑和图片上传