SOURCE

console 命令行工具 X clear

                    
>
console
$(document).ready(function(){
    console.log('ready');
});

function run() {
    var viewEdit = document.getElementById('editview');
    var text = viewEdit.innerText;
    if (text) {
        try{
            var res = JSON.parse(text.trim());
            if (res) {
                var data = [];
                var info = {
                    myhead:'http://cdn.jsrun.top/avatar/default.png',
                    theirhead: 'http://cdn.jsrun.top/avatar/26322_1582213521787.png'
                };//聊天室信息
                if (Array.isArray(res)) data = res;
                else{
                    data = res.list;
                    
                    if (res.info) {
                        info = res.info;
                    }
                }
                var html = '';
                data.forEach(function(item,i){
                    switch (item.sender){
                        case 'my':
                            html += '<div class="m-msg m-msg-my">';
                            html += '<img src="'+info.myhead+'" />';
                            html += '<div><pre>'+item.msg+'</pre></div></div>';
                        break;
                        default:
                            if (!item.msg) break;
                            html += '<div class="m-msg m-msg-their">';
                            html += '<img src="'+info.theirhead+'" />';
                            html += '<div><pre>'+item.msg+'</pre></div></div>';
                    }
                });
                document.getElementById('msglist').innerHTML = html;
                //console.log('ok...', data);
                viewEdit.innerText = '';
            }else {
                console.warn('empty...', res);
                alert('输入JSON数据为空,或非数组');
            }
        }catch(e){
            console.error('err...', data);
            alert('输入数据不合法'+e.message);
        }
    }else alert('请输入JSON数据');
}

function doScreenShot(){
    var listElem = document.getElementById('msglist');
    html2canvas(listElem, {
        allowTaint: false,
        useCORS: true
    }).then(canvas => {
        let url = canvas.toDataURL();
        console.log('img src',url);
        top.window.open(url, '_blank');
        return;
        let oImg = new Image();
        oImg.src = url;
        document.body.appendChild(oImg);
    console.log(oImg);
    });
}

// edited from https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob#Polyfill
var dataURIToBlob =  function (imgName, dataURI, callback) {
    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);
    }

    callback(imgName, new Blob([arr]));
}

var callback = function (imgName, blob) {
    var triggerDownload = $("<a>").attr("href", URL.createObjectURL(blob)).attr("download", imgName).appendTo("body").on("click", function () {
        if (navigator.msSaveBlob) {
            return navigator.msSaveBlob(blob, imgName);
        }
    });
    triggerDownload[0].click();
    triggerDownload.remove();
};

function createImg() {
    var getPixelRatio = function (context) { // 获取设备的PixelRatio
        var backingStore = context.backingStorePixelRatio ||
                        context.webkitBackingStorePixelRatio ||
                        context.mozBackingStorePixelRatio ||
                        context.msBackingStorePixelRatio ||
                        context.oBackingStorePixelRatio ||
                        context.backingStorePixelRatio || 0.5;
        return (window.devicePixelRatio || 0.5) / backingStore;
    };
    //生成的图片名称
    var imgName = "cs.png";
    var shareContent = document.getElementById("msglist");
    console.log('shareContent', shareContent);
    let scale = 3;
    var opts = {
        //scale: scale,
        /*canvas: canvas,
        width: width,
        height: height,*/
        dpi: window.devicePixelRatio,
        useCORS: true, // 【重要】开启跨域配置
        //width: window.screen.availWidth,  //显示的canvas窗口的宽度
        //height: window.screen.availHeight, //显示的canvas窗口的高度
        width: shareContent.offsetWidth,   //获取当前网页的宽度
        height: shareContent.offsetHeight, //获取当前网页的高度
        windowWidth: shareContent.scrollWidth,     //获取X方向滚动条内容
        windowHeight: shareContent.scrollHeight, //获取Y方向滚动条内容
        x: 0,                                                                            //页面在水平方向没有滚动,故设置为0
        y: window.pageYOffset                                            //页面在垂直方向的滚动距离
    };
    html2canvas(shareContent, opts).then(function (canvas) {
        const context = canvas.getContext("2d");

        // 【重要】关闭抗锯齿 https://segmentfault.com/a/1190000011478657
        context.imageSmoothingEnabled = false;
        context.webkitImageSmoothingEnabled = false;
        context.msImageSmoothingEnabled = false;
        context.imageSmoothingEnabled = false;
        let imgUrl = canvas.toDataURL("image/png").replace("image/png","image/octet-stream");
        //console.log("imgUrl",imgUrl);
        dataURIToBlob(imgName, imgUrl, callback);
    });
}
<div class="m-page">
    <div class="m-page-title">
        <a>﹤</a>
        <div class="m-title">与TA聊天</div>
        <a title="截图" onclick="createImg()">⊙</a>
    </div>
    <div class="m-page-body" id="msglist">
        <div class="m-msg m-msg-their">
            <img alt="their" src="http://cdn.jsrun.top/avatar/26322_1582213521787.png" />
            <div><pre>您好,请输入JSON格式内容,点击 ‘发送‘即可生成聊天记录.
JSON格式是 [{ "sender":"their", "msg":"1" },{ "sender":"my", "msg":"2" }]</pre></div>
        </div>
        <div class="m-msg m-msg-my">
            <img alt="my" src="http://cdn.jsrun.top/avatar/default.png" />
            <div><pre>好的</pre></div>
        </div>
    </div>
    <div class="m-page-footer">
        <div class="m-textarea" contenteditable="true" id="editview">
            [
                {
                    "msg":"看来,苹果过去对这件事的态度是睁一只眼闭一只眼,热更新也早已成为开发者们青睐的一门技术。王哲介绍到国内绝大多数 iOS 手游,不论是 Cocos 还是 Unity,都在用热更新功能,腾讯和网易也在使用脚本对游戏进行小版本热更新。"
                },
                {
                    "msg":"如果只是为了提高用户体验,这点和苹果的利益出发点是高度一致的。"
                },
                {
                    "msg":"苹果之前没有对热更新痛下杀手的。然而确实也有不少开发者利用这个功能,做一些触犯苹果底线的事情。"
                },
                {
                    "msg":"别干坏事,如果大家只是为了提高用户体验,提高运营效率,不作恶,就没什么原则上的问题了,剩下的只是技术上的小修复而已。"
                },
                {
                    "sender":"my",
                    "msg":"我就想知道以后12306是不是不能强制自动更新了?如果是,那真是让人拍手称快~"
                },
                {
                    "msg":"12306:苹果你是不是不想在中国卖了?"
                },
                {
                    "sender":"my",
                    "msg":"王者荣耀加载时的更新算么?"
                },
                {
                    "msg":"算热更新,不过一般来说游戏里面用的是lua热更,不在这次的波及范围内"
                },
                {
                    "sender":"",
                    "msg":""
                }
            ]
        </div>
        <a class="m-btn-send" onclick="run()">发送</a>
    </div>
</div>
:root {
    --colorThemeBg: #F3F5F6;
    --colorFocusBg: #549BED;
    --colorTitleBg: #29292B;
    --colorFontW: white;
    --colorBorder: #D4D4D5;
    --colorMsgBgG: #89EC3A;
}
html,body{
    height: 100%;
}
body {
    margin: 0;
    padding: 0;
    font-size: 24px; 
    background-color: black;
}
a{
    padding: 2vh 1vw;
}
a:hover {
    color: white;
    background-color: var(--colorFocusBg);
}
.m-page {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    max-width: 480px;
    margin: auto;
    background-color: var(--colorThemeBg);
}
.m-page-title {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    display: flex;
    flex-direction: row;
    background-color: var(--colorTitleBg);
    color: var(--colorFontW);
}
.m-page-title>a,.m-page-title>div{
    flex: 0;
    white-space: nowrap;
}
.m-page-title>.m-title {
    flex: 1;
    padding: 2vh 0;
    border-top: 1px solid green;
    text-align: center;
}
.m-page-footer {
    position: absolute;
    bottom: 0;
    right: 0;
    left: 0;
    display: flex;
    flex-direction: row;
    align-items: center;
    background-color: white;
    padding: 1vh;
}
.m-page-footer>.m-textarea{
    flex: 1;
    padding: 1vw;
    box-sizing: border-box;
    min-height: 4vh;
    max-height: 10vh;
    border: 1px solid var(--colorBorder);
    word-break: break-all;
    overflow-y: auto;
}
.m-page-footer>.m-btn-send{
    flex: 0;
    padding: 0 1vw;
    white-space: nowrap;
}
.m-page-body {
    position: absolute;
    top: 9vh;
    left: 0;
    right: 0;
    bottom: 9vh;
    overflow-y: auto;
}
.m-msg {
    display: flex;
    padding: 1vw;
    padding-top: 0;
    align-items: flex-start;
}
.m-msg-their {
    flex-direction: row;
}
.m-msg-my {
    flex-direction: row-reverse;
    text-align: right;
}
.m-msg>img {
    flex: 0;
    width: 60px;
    height: 60px;
}
.m-msg>div {
    flex: 1;
}
.m-msg pre {
    display: inline-block;
    margin: 1vw;
    margin-top: 0;
    padding: 1vw;
    width: auto;
    border-radius: 5px;
    box-shadow: 0 1px var(--colorBorder);
    word-break: break-all;
    white-space: pre-wrap;
}
.m-msg-their pre {
    background-color: white;
}
.m-msg-my pre {
    background-color: var(--colorMsgBgG);
    text-align: left;
}

本项目引用的自定义外部资源