【前端】常用总结(一)


阅读目录

一、canvas截图

二、分组间元素拖动

三、占位符交互效果

四、导出Excel/Zip文件

一、canvas截图

1 需求

页面内的某块容器截图,截取的图片需要去除不需要的元素

2 canvas实现

//截图
function capturePicture(){
    //修改全局视图样式   借助vue实现可以在此处先把页面上不需要截取元素隐藏掉
    //this.capture_status = true;

    //base64转blob
    function dataURIToBlob(dataURI) {
        var binStr = atob(dataURI.split(',')[1]),
            len = binStr.length,
            arr = new Uint8Array(len);

        for (var i = 0; i < len; i++) {
            arr[i] = binStr.charCodeAt(i);
        }
        let blobs = new Blob([arr]);
        return blobs;
    }

    function _fixType(type) {
        type = type.toLowerCase().replace(/jpg/i, 'jpeg');
        let r = type.match(/png|jpeg|bmp|gif/)[0];
        return 'image/' + r;
    }
    //唤起浏览器下载
    function fileDownload(dataUrl) {
        let aLink = document.createElement('a');
        aLink.style.display = 'none';
        aLink.href = URL.createObjectURL(dataURIToBlob(dataUrl));
        aLink.download = `${formatTimeToYMD(getNowTime())}项目统计.jpg`; //图片名称
        // 触发点击-然后移除
        document.body.appendChild(aLink);
        aLink.click();
        document.body.removeChild(aLink);
    }

    setTimeout(()=>{ //这里加等待时间是为了确保上面设置的页面元素改变之后在截取
        const ele = document.getElementById("jira-container");  //截图容器
        const config = {
            allowTaint: true,
            scale: 1
        };
        html2canvas(ele, config).then(canvas => {
            var type = 'jpg';
            var imgData = canvas.toDataURL(type); //canvas转换为图片
            // 加工image data,替换mime type,方便以后唤起浏览器下载
            imgData = imgData.replace(_fixType(type), 'image/octet-stream');
            fileDownload(imgData);
            this.capture_status = false;
        })
    }, 300)
},

3 问题

截图的图片如果超出了屏幕大小,请滚动到页面最上部分截取,否则会有截取信息缺失,原因暂时不详。

二、分组间元素拖动

1 需求

多个分组之间实现元素拖动

1.1 例子

分组a: [{"name": "vue.draggable","order": 1,"fixed": false},{"name": "draggable","order": 2,"fixed": false}]
分组b: [{"name": "vue.draggable","order": 3,"fixed": false},{"name": "draggable","order": 4,"fixed": false}]
实现a,b中的元素可以通过拖拽DOM改变

2 Vue.Draggable实现

2.1 html

<draggable
    class="dragArea list-group"
    :list="list_a"   //放入
    :clone="clone"   //设置后按住ctrl拖拽会复制一行
    :group="{ name: 'people', pull: pullFunction }"    //name:分组名称, pull:拖动时回调函数
    @start="start"   //开始拖拽的时候回调函数
  >
  <div v-for="(item, index) in list_a"></div>
</draggable>

<draggable class="dragArea list-group" :clone="clone" :list="list_b" group="people">   //需要指定group所属分组
  <div v-for="(item, index) in list_b"></div>
</draggable>

2.2 js

data() {
    return {
        controlOnStart: true,
    }
}
methods: {
    clone(args) {
        return JSON.parse(JSON.stringify(args))
    },
    pullFunction() {
      return this.controlOnStart ? "clone" : true;
    },
    start({ originalEvent }) {
      this.controlOnStart = originalEvent.ctrlKey;  //是否按ctrl键
    },
}

3 问题

假如组内元素是可以输入的,常用操作移动鼠标拉选内容就会很不方便。

三、占位符交互效果

1 需求

Material Design规范中占位符交互效果,实现修改用户名

2 实现

2.1 html

  <div class="input-box">
    <div class="input-outline-x">
        <input class="input-control input-outline" placeholder="新用户名称" v-model="user_info.user_name"/>
        <label class="input-label">新用户名称</label>
        <span class="span-desc">4-30个字符</span>
    </div>
    <div class="input-box-button">
      <el-button type="primary" size="small" @click="submit">确 定</el-button>  //修改操作
      <el-button size="small" @click="activeName=''">取 消</el-button>
    </div>
  </div>

2.2 css

.input-outline-x{
    margin-top: 10px;
    width: -moz-fit-content;
    width: fit-content;
    position: relative;
}
.input-fill-x {
    border-bottom: 1px solid #d0d0d5;
}
.input-fill-x::after {
    content: '';
    position: absolute;
    border-bottom: 2px solid #2486ff;
    left: 0; right: 0; bottom: -1px;
    transform: scaleX(0);
    transition: transform .25s;
}
.input-fill-x:focus-within::after {
    transform: scaleX(1);
}

3 优势

借助CSS placeholder-shown伪类,纯CSS,无任何JS,实现这样的占位符交互效果。

四、导出Excel/Zip文件

1.导出excel

1.1导出代码

import XLSX from 'xlsx'

function export_json_to_excel({
  multiHeader = [],
  header,
  data,
  filename,
  merges = [],
  autoWidth = true,
  bookType=  'xlsx'
} = {}) {
  /* original data */
  filename = filename || 'excel-list'
  data = [...data]
  data.unshift(header);

  for (let i = multiHeader.length-1; i > -1; i--) {
    data.unshift(multiHeader[i])
  }

  var ws_name = "SheetJS";
  var wb = new Workbook(),
    ws = sheet_from_array_of_arrays(data);

  if (merges.length > 0) {
    if (!ws['!merges']) ws['!merges'] = [];
    merges.forEach(item => {
      ws['!merges'].push(XLSX.utils.decode_range(item))
    })
  }

  if (autoWidth) {
    /*设置worksheet每列的最大宽度*/
    const colWidth = data.map(row => row.map(val => {
      /*先判断是否为null/undefined*/
      if (val == null) {
        return {
          'wch': 10
        };
      }
      /*再判断是否为中文*/
      else if (val.toString().charCodeAt(0) > 255) {
        return {
          'wch': val.toString().length * 2
        };
      } else {
        return {
          'wch': val.toString().length
        };
      }
    }))
    /*以第一行为初始值*/
    let result = colWidth[0];
    for (let i = 1; i < colWidth.length; i++) {
      for (let j = 0; j < colWidth[i].length; j++) {
        if (result[j]['wch'] < colWidth[i][j]['wch']) {
          result[j]['wch'] = colWidth[i][j]['wch'];
        }
      }
    }
    ws['!cols'] = result;
  }

  /* add worksheet to workbook */
  wb.SheetNames.push(ws_name);
  wb.Sheets[ws_name] = ws;

  var wbout = XLSX.write(wb, {
    bookType: bookType,
    bookSST: false,
    type: 'binary'
  });
  saveAs(new Blob([s2ab(wbout)], {
    type: "application/octet-stream"
  }), `${filename}.${bookType}`);
}

1.2使用

const data = [{"name": "dc", "arg": 10}]

//格式化数据,将data数据转化成[["dc", 10], ]
formatJson(filterVal, jsonData) {
    return jsonData.map(v => filterVal.map(j => {
        return v[j]
    }))
}
//
export_json_to_excel.then(excel => {
    const tHeader = ['姓名', '年龄']
    const filterVal = ['name', 'arg']
    const data = formatJson(filterVal, data)
    excel.export_json_to_excel({
      header: tHeader,
      data,
      filename: '姓名'
    })
  })

2.导出多sheet页excel

2.1导出代码

import XLSX from 'xlsx'

//数据写入sheet页对象
function export_write_to_sheet({
  multiHeader = [],
  header,
  data,
  merges = [],
  autoWidth = false,

} = {}) {
  /* original data */
  data = [...data]
  data.unshift(header);

  for (let i = multiHeader.length-1; i > -1; i--) {
    data.unshift(multiHeader[i])
  }
  var ws = sheet_from_array_of_arrays(data);

  if (merges.length > 0) {
    if (!ws['!merges']) ws['!merges'] = [];
    merges.forEach(item => {
      ws['!merges'].push(XLSX.utils.decode_range(item))
    })
  }
  return ws
}

// sheet页对象信息写入excel
function writer_sheet_data_to_excle(filename, data) {
  var wb = new Workbook()

  for(let i=0;i<data.length;i++){
    /* add worksheet to workbook */
    wb.SheetNames.push(data[i][0]);
    wb.Sheets[data[i][0]] = data[i][1];
  }
  // filename = filename || 'excel-list';
  var wbout = XLSX.write(wb, {
    bookType: 'xlsx',
    bookSST: false,
    type: 'binary'
  });
  saveAs(new Blob([s2ab(wbout)], {
    type: "application/octet-stream"
  }), `${filename}.xlsx`);

}

2.2使用

const data1 = [{"name": "dc", "arg": 10}]
const data2 = [{"name1": "dz", "arg1": 15}]

//格式化数据
formatJson(filterVal, jsonData) {
  return jsonData.map(v => filterVal.map(j => {
    return v[j]
}))
const t1Filter = ['name', 'arg'];
const t2Filter = ['name1', 'arg1'];
const t1Header = ['姓名', '年龄']
const t2Header = ['姓名1', '年龄1']
let record_data = [];
// 格式化数据
const fdata1 = formatJson(t1Filter, data1);  
const fdata2 = formatJson(t2Filter, data2);
// 数据写入sheet页对象
const ws1 = excel.export_write_to_sheet({ header: t1Header, data:fdata1})
const ws2 = excel.export_write_to_sheet({ header: t2Header, data:fdata2})

record_data.push(['sheet1', ws1]);
record_data.push(['sheet2', ws2]);
# 循环添加sheet对象信息
excel.writer_sheet_data_to_excle('多sheet页', record_data)

3.导出Zip

require('script-loader!file-saver');
import JSZip from 'jszip'

// 导出zip压缩文件
export function export_txt_to_zip(th, jsonData, txtName, zipName) {
  const zip = new JSZip()
  const txt_name = txtName || 'file'
  const zip_name = zipName || 'file'
  const data = jsonData
  let txtData = `${th}\r\n`
  data.forEach((row) => {
    let tempStr = ''
    tempStr = row.toString()
    txtData += `${tempStr}\r\n`
  })
  zip.file(`${txt_name}.txt`, txtData)
  zip.generateAsync({
    type: "blob"
  }).then((blob) => {
    saveAs(blob, `${zip_name}.zip`)
  }, (err) => {
    alert('导出失败')
  })
}
posted @ 2020-01-15 16:41  初遇ぃ  阅读(297)  评论(0编辑  收藏  举报
//一下两个链接最好自己保存下来,再上传到自己的博客园的“文件”选项中 //一下两个链接最好自己保存下来,再上传到自己的博客园的“文件”选项中