一、html转为canvas
1.安装 html2canvas

cnpm install html2canvas --save

2.引入 html2canvas

// 引入
import html2canvas from "html2canvas"

3.待转换内容

<div ref="lessonTableImg" class="table-container">
...
</div>

4.html转为canvas,并下载

        download () {
        	// 获取待转换对象
            var downloadContent = this.$refs.lessonTableImg
            
            .....
            // 转换并下载
            html2canvas(downloadContent, opts).then((canvas) => {
                
                let dataURL = canvas.toDataURL('image/png')

                // 下载图片
                let a = document.createElement('a')
                document.body.appendChild(a)
                a.href = img.src
                // 设置下载标题
                a.download = this.lessonDto.week + "排课计划"
                a.click()
            })
        }

二、提高图片的清晰度

其基本原理为:
将canvas的属性width和height属性放大为2倍(或者设置为devicePixelRatio倍),最后将canvas的CSS样式width和height设置为原先1倍的大小。

例如:希望在html中实际显示的宽高分别为160px,90px则可作如下设置

<canvas width="320" height="180" style="width:160px;height:90px;"></canvas>

具体办法:

  1. 更改百分比布局为px布局(如果原先是百分比布局的话)
  2. 关闭canvas默认的抗锯齿设置
  3. 设置模糊元素的width和height为素材原有宽高,然后通过transform: scale进行缩放。这里scale的数值由具体需求决定

在这过程中,需要用到 canvas2image 插件

1.安装 canvas2image

cnpm install canvas2image --save

2.引入 canvas2image
因为总是引入模块失败,所以我将该插件的js代码复制到本地,然后从本地引入。复制到本地时,记得在末尾加上

export default Canvas2Image;
// 引入
import Canvas2Image from '../../../utils/canvas2image'

3.改造上面的第4步:html转为canvas,并下载

        download () {
            var downloadContent = this.$refs.lessonTableImg
            var width  = downloadContent.offsetWidth
            var height  = downloadContent.offsetHeight
            var canvas = document.createElement('canvas')
            var scale = 2
            canvas.width = width * 2
            canvas.height = height * scale
            canvas.getContext('2d').scale(scale, scale)
            var opts = {
                scale: scale,
                canvas: canvas,
                // 日志开关,便于查看html2canvas的内部执行流程
                // logging: true,
                width: width,
                height: height,
                // 避免下载不全
                backgroundColor: null,
                // 【重要】开启跨域配置
                useCORS: true
            }

            html2canvas(downloadContent, opts).then((canvas) => {
                var context = canvas.getContext('2d')
                // 【重要】关闭抗锯齿
                context.mozImageSmoothingEnabled = false
                context.webkitImageSmoothingEnabled = false
                context.msImageSmoothingEnabled = false
                context.imageSmoothingEnabled = false

                var img = Canvas2Image.convertToJPEG(canvas, canvas.width/2, canvas.height/2)
                
                let dataURL = img.getAttribute('src')

                // 下载图片
                let a = document.createElement('a')
                document.body.appendChild(a)
                a.href = img.src
                // 设置下载标题
                a.download = this.lessonDto.week + "排课计划"
                a.click()

            })
        }

完整案例如下:

<template>
    <div>
        <div class="searchContainer">
            <el-button size="mini" type="primary" @click="searchLessons">查询课表</el-button>
            <el-button size="mini" type="danger" @click="download" v-if="tableVisible">下载课表</el-button>
        </div>
        <div ref="lessonTableImg" class="table-container">
            <el-table
            v-loading="tableLoading"
            v-if="tableVisible"
            :data="lessonDto.plans"
            stripe
            border 
            fit
            :header-cell-style="headerCellStyle"
            style="width: 100%">
                <el-table-column :label="lessonDto.week + '排课计划'" align="center">
                    <el-table-column prop="period" align="center" label="时间段" style="width: 14%"></el-table-column>
                    <el-table-column align="center" :label="lessonDto.times[0]" style="width: 14%">            
                        <template slot-scope="scope">
                            <div v-html="scope.row.mon"></div>
                        </template>
                    </el-table-column>
                    <el-table-column align="center" :label="lessonDto.times[1]" style="width: 14%">   
                        <template slot-scope="scope">
                            <div v-html="scope.row.tue"></div>
                        </template>
                    </el-table-column>
                    <el-table-column align="center" :label="lessonDto.times[2]" style="width: 14%">
                        <template slot-scope="scope">
                            <div v-html="scope.row.wed"></div>
                        </template>
                    </el-table-column>
                    <el-table-column align="center" :label="lessonDto.times[3]" style="width: 14%">
                        <template slot-scope="scope">
                            <div v-html="scope.row.thurs"></div>
                        </template>
                    </el-table-column>
                    <el-table-column align="center" :label="lessonDto.times[4]" style="width: 14%">
                        <template slot-scope="scope">
                            <div v-html="scope.row.fri"></div>
                        </template>
                    </el-table-column>
                    <el-table-column align="center" :label="lessonDto.times[5]" style="width: 14%">
                        <template slot-scope="scope">
                            <div v-html="scope.row.sat"></div>
                        </template>
                    </el-table-column>
                    <el-table-column align="center" :label="lessonDto.times[6]" style="width: 14%">
                        <template slot-scope="scope">
                            <div v-html="scope.row.sun"></div>
                        </template>
                    </el-table-column>
                </el-table-column>
            </el-table>
        </div>
    </div>
</template>
<script>
import html2canvas from "html2canvas"
import Canvas2Image from '../../../utils/canvas2image'

export default {
    name: 'PlanShow',
    data() {
        return {
            lessonDto: {},
            lessons: [],
            tableLoading: false,
            tableVisible: false,
            subjectVisible: false,
            teacherVisible: true
        }
    },
    methods: {
        searchLessons () {
            this.tableLoading = true
            this.getRequestWithParams('/lesson/basic', {
                startTime: this.selectedDate,
                userId: this.userId,
                subjectId: this.subjectId,
                campusId: this.campusId
            }).then(resp => {
                this.tableLoading = false
                // 置空
                this.lessonDto = {}
                if (resp && resp.status == 200 && resp.data.status == 200) {
                    var lessons = resp.data.obj
                    if (lessons instanceof Array && lessons.length > 0) {
                        var lesson = lessons[0]
                        this.lessons = lesson.plans
                        var plans = lesson.plans
                        var newPlans = []
                        if (plans instanceof Array && plans.length > 0) {
                            plans.forEach(plan => {
                                var newPlan = {
                                    period: plan.period,
                                    mon: this.showLesson(plan.mon), 
                                    tue: this.showLesson(plan.tue),  
                                    wed: this.showLesson(plan.wed),  
                                    thurs: this.showLesson(plan.thurs),  
                                    fri: this.showLesson(plan.fri),  
                                    sat: this.showLesson(plan.sat),  
                                    sun: this.showLesson(plan.sun)                                        
                                }
                                newPlans.push(newPlan)
                            })
                        }
                        this.lessonDto = {
                            week: lesson.week,
                            plans: newPlans,
                            times: this.handleTime(new Date(lesson.monday))
                        }
                        this.tableVisible = true
                    } else {
                        this.tableVisible = false
                        this.$message('暂无排课计划!')
                    }                    
                }
            })
        },
        headerCellStyle ({row, column, rowIndex, columnIndex}) {
            if (rowIndex === 0 && columnIndex === 0) {
                // 设置标题栏样式
                return {background: '#fff', color: '#000', 'font-size': '20px', 'font-weight': 'bold'}
            } else {
                // 普通表头样式
                return {background: '#409EFF', color: '#fff'}
            }
        },
        download () {
            var downloadContent = this.$refs.lessonTableImg
            var width  = downloadContent.offsetWidth
            var height  = downloadContent.offsetHeight
            var canvas = document.createElement('canvas')
            var scale = 2
            canvas.width = width * 2
            canvas.height = height * scale
            canvas.getContext('2d').scale(scale, scale)
            var opts = {
                scale: scale,
                canvas: canvas,
                // 日志开关,便于查看html2canvas的内部执行流程
                // logging: true,
                width: width,
                height: height,
                // 避免下载不全
                backgroundColor: null,
                // 【重要】开启跨域配置
                useCORS: true
            }

            html2canvas(downloadContent, opts).then((canvas) => {
                var context = canvas.getContext('2d')
                // 【重要】关闭抗锯齿
                context.mozImageSmoothingEnabled = false
                context.webkitImageSmoothingEnabled = false
                context.msImageSmoothingEnabled = false
                context.imageSmoothingEnabled = false

                var img = Canvas2Image.convertToJPEG(canvas, canvas.width/2, canvas.height/2)
                
                let dataURL = img.getAttribute('src')

                // 下载图片
                let a = document.createElement('a')
                document.body.appendChild(a)
                a.href = img.src
                // 设置下载标题
                a.download = this.lessonDto.week + "排课计划"
                a.click()

            })
        }
    },
    props: {
        subjects: Array,
        teachers: Array,
        selectedDate: String,
        campusId: String,
        subjectId: String,
        userId: String
    }
}
</script>
<style lang="stylus" scoped>
    .searchContainer
        width 100%
        display flex
        justify-content center
    .table-container
        margin-top 20px
</style>

参见 基于html2canvas实现网页保存为图片及图片清晰度优化

Logo

前往低代码交流专区

更多推荐