LOGI

Typecho 插入二维码的简单方法

说到简单,使用已有 API 当然是最简单的,但自建后端有一定成本,公共 API 又容易失效,不如用 js 封装一个只依赖浏览器且永不失效的前端 API 吧。

[collapse title="Example"]

[/collapse]

引入 JS

依次进入 控制台 - 外观 - 设置外观 - 主题自定义扩展,将以下代码加入到 自定义 HTML 元素拓展 - 标签: head 头部 (meta 元素后),也可直接加入到主题对应的 header.php 中的 </head> 标签前。

[collapse title="JavaScript Code"]

<script>
    // QRCODE API
    document.addEventListener('DOMContentLoaded', initQrcode);
    function initQrcode() {
        const common = {
            loadResource: function (id, resource, type, callback) {
                let loaded = document.head.querySelector('#' + id);
                if (loaded) {
                    callback();
                    return;
                }
                const element = document.createElement(type);
                element.onload = element.onreadystatechange = () => {
                    if (!loaded && (!element.readyState || /loaded|complete/.test(element.readyState))) {
                        element.onload = element.onreadystatechange = null;
                        loaded = true;
                        callback();
                    }
                }
                if (type === 'link') {
                    element.rel = 'stylesheet';
                    element.href = resource;
                } else {
                    element.src = resource;
                }
                element.id = id;
                document.getElementsByTagName('head')[0].appendChild(element);
            },
            loadResources: function (callback) {
                const cdn = '//s0.pstatp.com/cdn/expire-1-M';
                const resources = ['/jquery.qrcode/1.0/jquery.qrcode.min.js'];
                let unloadedResourceCount = resources.length;
                resources.forEach(resource => {
                    this.loadResource(btoa(resource).replace(/[=+\/]/g, ''), cdn + resource,
                        ({
                            'css': 'link',
                            'js': 'script'
                        })[resource.split('.').pop()],
                        () => --unloadedResourceCount ? null : callback()
                    );
                });
            },
            initOptions: function (source, options) {
                options = options || {};
                'text size border'.split(' ').forEach(key => {
                    const value = source instanceof URLSearchParams ? source.get(key) : source.getAttribute(key);
                    if (value) {
                        if (key === 'size') {
                            options.width = value;
                            options.height = value;
                        } else {
                            options[key] = value;
                        }
                    }
                });
                return options;
            },
            makeQrcode: function (source, options) {
                const div = document.createElement('div');
                jQuery(div).qrcode(options);
                const canvas = div.querySelector('canvas');
                const dataURL = canvas.toDataURL('image/jpeg', 1.0);
                if (!options.hasOwnProperty('border')) {
                    source.src = dataURL;
                    return;
                }
                const context = canvas.getContext('2d');
                const image = new Image();
                image.onload = function () {
                    const size = options.width - 2 * options.border;
                    context.fillStyle = "#FFF";
                    context.fillRect(0, 0, canvas.width, canvas.height);
                    context.drawImage(image, options.border, options.border, size, size);
                    source.src = canvas.toDataURL('image/jpeg', 1.0);
                };
                image.src = dataURL;
            },
            makeQrcodes: function (sources) {
                for (let i = 0; i < sources.length; i++) {
                    const options = this.initOptions(sources[i]);
                    if (options.hasOwnProperty('text')) {
                        const image = new Image();
                        sources[i].parentNode.insertBefore(image, sources[i]);
                        sources[i].style.display = 'none';
                        this.makeQrcode(image, options);
                    }
                }
            }
        };
        const mirages = {
            addQrcode: function (qrBox, makeQrcode, initOptions) {
                const image = qrBox.querySelector('img');
                if (!image.src.startWith(location.href)) {
                    return;
                }
                const splitedSrc = image.src.split('?');
                let options = { text: splitedSrc[0] };
                if (splitedSrc[1]) {
                    options = initOptions(new URLSearchParams(splitedSrc[1]), options);
                }
                makeQrcode(image, options);
            }
        };
        const position = document.querySelector('.post-qr-code-box');
        const qrs = document.getElementsByTagName('qr');
        if (position) {
            common.loadResources(() => {
                if (qrs.length !== 0) common.makeQrcodes(qrs);
                mirages.addQrcode(position, common.makeQrcode, common.initOptions);
            });
        } else if (qrs.length !== 0) {
            common.loadResources(() => common.makeQrcodes(qrs));
        }
    };
</script>

[/collapse]

如果你开启了 PJAX,还需单独加入回调函数。对于本主题,依次进入 控制台 - 外观 - 设置外观 - PJAX(BETA) - PJAX RELOAD,将 initQrcode(); 添加进入即可。

添加二维码

html 形式将以下内容写入文章中,便可创建二维码。其中 text编码内容,为 必填 属性。后两者为可选属性,分别用于指定二维码和边框大小。

!!!
<qr text="https://logi.im" size="300" border="15"></qr>
!!!

本文二维码

本主题作者为 PC 页面添加了文章二维码功能,你可在 控制台 - 外观 - 设置外观 - 二维码及打赏 - 本页二维码生成地址 中填入 {{%LINK}}?size=250&border=15 打开它,大小和边框可以自定义,效果见本文 PC 端。

最后送几个 OneDrive 5T 账号,回复后刷新可见,请每人只拿一个。更多博客内容,点击我查看

[hide]

[/hide]

当前页面是本站的「Google AMP」版。查看和发表评论请点击:完整版 »