吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 7357|回复: 41
上一主题 下一主题
收起左侧

[其他转载] 【HTML+js】微信微博九宫格图拆分器

  [复制链接]
跳转到指定楼层
楼主
南郊居士 发表于 2020-2-16 22:12 回帖奖励
本帖最后由 南郊居士 于 2020-2-17 22:44 编辑

最后一次更新本帖,以后对本工具的任何修改都不再另行发布了:


2020.2.17
1.新增了心形裁剪功能


为制作这个功能,绘制心形线时遇到困难,因为找不到现成的工具,所以又另做了一个新工具:三次贝塞尔曲线坐标手工拟合并生成,链接:https://www.52pojie.cn/thread-1108704-1-1.html


---------------------------------- 正文分割线 ----------------------------------------

网上很多教程在教如何制做微博微信九宫格图片(据说安卓微博自带这个功能,但是果机不行),有用PS的,有需要安装App的,有用微信小程序的,不一而足。


其实这是个非常简单的小功能,写个前端页就可以轻松搞定,你只需要一张美美的照片和一个支持H5的浏览器就够了。


名称:微信四九城(随便乱起的名字,因为可以生成4张或9张图)
功能:
1、图片的九宫格或四分格拆分并保存到本地,测试Chrome 80.0.3987.106、EMUI10.0系统浏览器和iOS 12.3.1 Safari均可正常使用。
2、图片旋转、图片裁剪。
3、支持图片的圆角矩形和圆形裁剪、裁剪掉的部分可选保留透明通道。
4、jpeg格式可以选择图片质量。


效果:





Safari不支持链接存图,只能长按保存,并不影响图片质量。


测试链接:http://gxsoftware.gitee.io/imageswall
只有一个html文件,源码自取。


界面自带劝退功能,和那些美美哒可爱多的微信小程序没有可比性,颜控退散

免费评分

参与人数 6吾爱币 +6 热心值 +5 收起 理由
jia2319885955 + 1 + 1 谢谢@Thanks!
黄三宝 + 1 + 1 学习学习
小众资源 + 1 + 1 谢谢@Thanks!
3094644 + 1 + 1 热心回复!
色色 + 1 + 1 感谢大佬 右键保存网页即可保存源码
飞龙project + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
众益科技 发表于 2020-2-19 22:20
南郊居士 发表于 2020-2-18 22:38
你可能被web劫持了,我的源码里没有这一段。

检查一下你的路由器吧。

小弟无才,复下来是这样的,运行不了


<!DOCTYPE html>
<!-- saved from url=(0038)http://gxsoftware.gitee.io/imageswall/ -->
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">


<meta name="viewport" content="width = device-width, height = device-height, maximum-scale = 1.0, user-scalable = no">

<style type="text/css">
.wx_button {
        border-spacing:0px;
        border-style: solid;
        border-color: #38f;
        border-width: 1px;
       
        display: inline-block;
        line-height: 2em;
        text-align: center;
        vertical-align: middle;
        background-color: #f8f8f8;
       
        -webkit-touch-callout: none;
        -webkit-user-select: none;
        -khtml-user-select: none;
        -moz-user-select: none;
        -ms-user-select: none;
        user-select: none;
}
.wx_image {
        width: 73px;
        height: 73px;
        margin: 1px;
        border:1px solid #000;
}
.wx_list {
        margin: 0;
        padding: 0;
        font-size: 0;
}
.wx_doing {
        position: fixed;
        top: 40%;
        height: 4em;
        left: 20%;
        right: 20%;
       
        background-color: #FFF;
        border: 3px solid #000;
        display: inline-block;
        line-height: 4em;
        vertical-align: middle;
        text-align: center;
}
</style>

<title>微信四九城</title>

</head>

<body>
        <h3>微信四九城</h3>
        <div style="margin: 1em 0">用于微信四分格和九分格图片的分割生成<br>纯前端,保护您的隐私</div>
        <div>
                <input id="upload_input" type="file" accept="image/*" style="display: none;">
                <label for="upload_input"><div class="wx_button" style="width: 8em;">点击选择图片</div></label>
                <input id="nine" type="radio" name="count" checked="checked"><label for="nine">九格</label>
                <input id="four" type="radio" name="count"><label for="four">四格</label>
        </div>
        <div id="make" style="margin: 1em 0; display: none;">
                <canvas id="canvas" style="margin: 0 0 1em 0; border: 1px solid #000;">不支持本功能</canvas><br>
                <div style="margin: 0 0 1em 0;">放大:<input type="range" id="enlarge" min="1" max="3" step="0.01" value="0" style="width: 15em;"></div>
                <div id="qua" style="margin: 0 0 1em 0;">质量:<input type="range" id="quality" min="0" max="100" step="1" value="75" style="width: 15em;"></div>
                <div style="margin: 0 0 1em 0;"><input id="alpha" type="checkbox"><label for="alpha">保留透明通道</label></div>
                <div style="margin: 0 0 1em 0;">
                        <input id="normal" type="radio" name="style" checked="checked"><label for="normal">不裁剪</label>
                        <input id="roundrect" type="radio" name="style"><label for="roundrect">圆角裁剪</label>
                        <input id="round" type="radio" name="style"><label for="round">圆形裁剪</label>
                        <input id="heart" type="radio" name="style"><label for="heart">心形裁剪</label>
                </div>
                <div class="wx_button" style="width: 8em; margin: 0 8px 0 0;">旋转90°</div><div class="wx_button" style="width: 8em;">生成</div>
        </div>
        <div id="result" style="margin: 1em 0; display: none;"></div>
        <div id="doing" class="wx_doing" style="display: none;">处理中,请勿操作</div>
        <hr>
        <small>GX Software 2020 by 南郊居士</small>
       
<script type="text/javascript">
var touchdown = false, preclick;
var l, t;
var img;
var doing = false;
CanvasRenderingContext2D.prototype.roundRect = function (x, y, w, h, r)
{
        if (w < 2 * r) {
                r = w / 2;
        }
        if (h < 2 * r) {
                r = h / 2;
        }
       
        this.beginPath();
        this.moveTo(x + r, y);
        this.arcTo(x + w, y, x + w, y + h, r);
        this.arcTo(x + w, y + h, x, y + h, r);
        this.arcTo(x, y + h, x, y, r);
        this.arcTo(x, y, x + w, y, r);
        this.closePath();
        return this;
}
CanvasRenderingContext2D.prototype.heart = function (x, y, r)
{
        this.translate(x, y);
        this.beginPath();
        this.moveTo(-0.004082 * r, -0.683418 * r);
        this.bezierCurveTo(-0.15102 * r, -1.030357 * r, -0.591837 * r, -1.11199 * r, -0.865306 * r, -0.793622 * r);
        this.bezierCurveTo(-1.036735 * r, -0.577296 * r, -1.02449 * r, -0.275255 * r, -0.914286 * r, -0.014031 * r);
        this.bezierCurveTo(-0.738776 * r, 0.369643 * r, -0.338776 * r, 0.581888 * r, -0.004082 * r, 0.998214 * r);
        this.bezierCurveTo(0.17551 * r, 0.745153 * r, 0.693878 * r, 0.385969 * r, 0.84898 * r, 0.096173 * r);
        this.bezierCurveTo(1.044898 * r, -0.173214 * r, 1.053061 * r, -0.66301 * r, 0.812245 * r, -0.846684 * r);
        this.bezierCurveTo(0.538776 * r, -1.107908 * r, 0.183673 * r, -1.026276 * r, -0.004082 * r, -0.683418 * r);
        this.closePath();
        this.translate(-x, -y);
        return this;
}
function isSafari()
{
        return (/Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent));
}
function loadPic(e)
{
        if (doing) {
                return;
        }
       
        var selectedFile = document.getElementById("upload_input").files[0];
        readFileData(selectedFile, function(image) {
                const test = document.getElementById("upload_input");
                test.outerHTML = test.outerHTML;
                const count = document.getElementById("nine").checked ? 9 : 4;
                l = t = 0;
                document.getElementById("enlarge").value = 0;
               
                const can = document.getElementById("canvas");
                try {
                        returnToEdit(false);
                        can.width = can.height = Math.min(window.innerWidth * 0.95, window.innerHeight * 0.75);
                       
                        if("ontouchstart" in window) {
                                can.addEventListener("touchstart", down, false);
                                can.addEventListener("touchmove", move, false);
                                window.addEventListener("touchend", up, false);
                        }
                        else {
                                can.addEventListener("mousedown", down, false);
                                can.addEventListener("mousemove", move, false);
                                window.addEventListener('mouseup', up, false);
                        }
                        draw();
                        window.scrollTo(0, can.offsetTop);
                }
                catch(e) {}
        });
}
function readFileData(file, callback)
{
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = function(e) {
                img = new Image();
                img.src = e.target.result;
                img.onload = function() {
                        var s = img.src.match(/data:.*;/)[0].match(/image.*;/)[0].match(/.*[^;]/)[0];
                        document.getElementById("qua").style.display = (s == "image/jpeg" || s == "image/webp") ? "" : "none";
                        callback(img);
                }
        }
}
function draw()
{
        if (!img) {
                return;
        }
       
        const count = document.getElementById("nine").checked ? 9 : 4;
        const len = Math.min(img.width, img.height);
        const can = document.getElementById("canvas");
        const ctx = can.getContext("2d");
        const width = can.width;
        const e = document.getElementById("enlarge").value;
       
        if (l + len / e > img.width) {
                l = img.width - len / e;
        }
        else if (l < 0) {
                l = 0;
        }
        if (t + len / e > img.height) {
                t = img.height - len / e;
        }
        else if (t < 0) {
                t = 0;
        }
       
        ctx.clearRect(0, 0, can.width, can.height);
        ctx.save();
        switch(getRadioValue("style"))
        {
        case 1:
                ctx.roundRect(0, 0, width, width, width / Math.sqrt(count) / 2);
                ctx.clip();
                break;
               
        case 2:
                ctx.beginPath();
                ctx.arc(width / 2, width / 2, width / 2, 0, 2 * Math.PI);
                ctx.clip();
                break;
               
        case 3:
                ctx.heart(width / 2, width / 2, width / 2);
                ctx.clip();
                break;
        }
        ctx.drawImage(img, l, t, len, len, 0, 0, width * e, width * e);
        if (count == 9) {
                const cw = width / 892 * 8;
                ctx.clearRect(width / 3 - cw / 2, 0, cw, width);
                ctx.clearRect(width / 3 * 2 - cw / 2, 0, cw, width);
                ctx.clearRect(0, width / 3 - cw / 2, width, cw);
                ctx.clearRect(0, width / 3 * 2 - cw / 2, width, cw);
        }
        else {
                const cw = width / 592 * 8;
                ctx.clearRect(width / 2 - cw / 2, 0, cw, width);
                ctx.clearRect(0, width / 2 - cw / 2, width, cw);
        }
        ctx.restore();
}
function getPos(c, e)
{
        var box = c.getBoundingClientRect();
       
        var x1, y1;
        if ("ontouchstart" in window) {
                if (e.targetTouches.length) {
                        x1 = e.targetTouches[0].clientX;
                        y1 = e.targetTouches[0].clientY;
                }
                else {
                        x1 = e.changedTouches[0].clientX;
                        y1 = e.changedTouches[0].clientY;
                        touchdown = false;
                }
        }
        else {
                x1 = e.clientX;
                y1 = e.clientY;
        }
       
        return {
                x: (x1 - box.left) * (c.width / box.width),
                y: (y1 - box.top) * (c.height / box.height)
        };
}
function prevent(e)
{
        if(window.event) {
                window.event.returnValue = false;
        }
        else {
                e.preventDefault();
        }
}
function down(e)
{
        if (doing) {
                return;
        }
        prevent(e);

        const p = getPos(document.getElementById("canvas"), e);
        if ("ontouchstart" in window) {
                if (!touchdown) {
                        touchdown = true;
                }
                else {
                        return;
                }
        }
       
        preclick = p;
}
function up(e)
{
        getPos(document.getElementById("canvas"), e);
        if (touchdown) {
                return;
        }
       
        preclick = null;
}
function move(e)
{
        if (!preclick) {
                return;
        }
       
        const en = document.getElementById("enlarge").value;
        const p = getPos(document.getElementById("canvas"), e);
        const len = Math.min(img.width, img.height);
        const can = document.getElementById("canvas");
       
        l -= (p.x - preclick.x) / can.width * len / en;
        t -= (p.y - preclick.y) / can.height * len / en;
       
        draw();
        preclick.x = p.x;
        preclick.y = p.y;
}
function make()
{
        setDoing(true);
        try {
                const e = document.getElementById("enlarge").value;
                const len = Math.min(img.width, img.height);
                const can = document.createElement("canvas");
                can.width = can.height = len;
                const ctx = can.getContext("2d");
               
                var s = img.src.match(/data:.*;/)[0].match(/image.*;/)[0].match(/.*[^;]/)[0];
                if (document.getElementById("alpha").checked && getRadioValue("style") != 0) {
                        s = "image/png";
                        ctx.clearRect(0, 0, can.width, can.height);
                }
                else if (!document.getElementById("alpha").checked) {
                        ctx.fillStyle = "#fff";
                        ctx.fillRect(0, 0, len, len);
                }
                switch(getRadioValue("style"))
                {
                case 1:
                        ctx.roundRect(0, 0, len, len, len / Math.sqrt(document.getElementById("nine").checked ? 9 : 4) / 2);
                        ctx.clip();
                        break;
                       
                case 2:
                        ctx.beginPath();
                        ctx.arc(len / 2, len / 2, len / 2, 0, 2 * Math.PI);
                        ctx.clip();
                        break;
                       
                case 3:
                        ctx.heart(len / 2, len / 2, len / 2);
                        ctx.clip();
                        break;
                }
                ctx.drawImage(img, l, t, len, len, 0, 0, len * e, len * e);
               
                var i = new Image();
                i.src = can.toDataURL(s, 1);
                i.onload = function() {
                        const len = this.width;
                        const count = document.getElementById("nine").checked ? 9 : 4;
                        const can = document.createElement("canvas");
                        const ctx = can.getContext("2d");
                        const quality = document.getElementById("quality");
                       
                        let inner = "";
                        if (isSafari()) {
                                inner += "长按图片保存";
                        }
                        else {
                                inner += "点击图片保存";
                        }
                       
                        var time = parseInt((new Date()).getTime() / 1000);
                        var s = this.src.match(/data:.*;/)[0].match(/image.*;/)[0].match(/.*[^;]/)[0];
                        if (count == 9) {
                                const size = can.width = can.height = len / 892 * 292;
                                for (let i = 0, x = 0, y = 0, index = 1; i < 3; i++) {
                                        inner += '<div class="wx_list">';
                                        for (let j = 0; j < 3; j++, index++) {
                                                ctx.clearRect(0, 0, can.width, can.height);
                                                ctx.drawImage(this, x, y, size, size, 0, 0, can.width, can.height);
                                                let url = can.toDataURL(s, quality.value / 100);
                                                inner += single(url, time, index);
                                                x += size + len / 892 * 8;
                                        }
                                        inner += "</div>";
                                        x = 0;
                                        y += size + len / 892 * 8;
                                }
                        }
                        else {
                                const size = can.width = can.height = len / 592 * 292;
                                for (let i = 0, x = 0, y = 0, index = 1; i < 2; i++) {
                                        inner += '<div class="wx_list">';
                                        for (let j = 0; j < 2; j++, index++) {
                                                ctx.clearRect(0, 0, can.width, can.height);
                                                ctx.drawImage(this, x, y, size, size, 0, 0, can.width, can.height);
                                                let url = can.toDataURL(s, quality.value / 100);
                                                inner += single(url, time, index);
                                                x += size + len / 592 * 8;
                                        }
                                        inner += "</div>";
                                        x = 0;
                                        y += size + len / 592 * 8;
                                }
                        }
                        inner += '<div class = "wx_button" style = "width: 8em; margin: 8px 0 0 0;">返回编辑</div>';
                        const r = document.getElementById("result");
                        r.innerHTML = inner;
                        r.style.display = "";
                        document.getElementById("make").style.display = "none";
                        setDoing(false);
                };
        }
        catch(e) {
                alert("转存失败!");
                setDoing(false);
        }
}
function returnToEdit(scroll)
{
        document.getElementById("make").style.display = "";
        document.getElementById("result").innerHTML = "";
        document.getElementById("result").style.display = "none";
        if (scroll) {
                window.scrollTo(0, document.getElementById("canvas").offsetTop);
        }
}
function rotate()
{
        setDoing(true);
        try {
                const can = document.createElement("canvas");
                can.width = img.height;
                can.height = img.width;
               
                const ctx = can.getContext("2d");
                ctx.translate(can.width / 2, can.height / 2);
                ctx.rotate(Math.PI / 2);
                ctx.drawImage(img, 0, 0, img.width, img.height, -img.width / 2, -img.height / 2, img.width, img.height);
               
                var i = new Image();
                var s = img.src.match(/data:.*;/)[0].match(/image.*;/)[0].match(/.*[^;]/)[0];
                i.src = can.toDataURL(s, 1);
                i.onload = function() {
                        setDoing(false);
                        img = this;
                        l = t = 0;
                        draw();
                }
        }
        catch(e) {
                alert("旋转失败!");
                setDoing(false);
        }
}
function setDoing(d)
{
        doing = d;
        document.getElementById("nine").disabled = doing;
        document.getElementById("four").disabled = doing;
        document.getElementById("doing").style.display = doing ? "" : "none";
}
function getRadioValue(name)
{
        var li = document.getElementsByName(name);
        for (var i = 0; i < li.length; i++) {
                if (li.checked) {
                        return i;
                }
        }
        return 0;
}
function single(url, time, index)
{
        if (isSafari()) {
                return `<img src=${url} class="wx_image"/>`;
        }
        else {
                return `<a download=${time}-${index} href=${url}><img src=${url} class="wx_image"/></a>`;
        }
}
</script>


</body></html>

微信图片_20200219221713.png (19.25 KB, 下载次数: 3)

微信图片_20200219221713.png
推荐
 楼主| 南郊居士 发表于 2020-3-25 20:20 |楼主
longjingo 发表于 2020-3-23 16:57
亲测透明通道不可用 显示黑色区域

可能和你的系统有关系,有的系统在应用中会将透明通道显示为黑色(举例,iOS的桌面图标要求必须有底色,透明通道将显示为黑色),这个时候就需要保留白底色,用于在某些系统中和背景色保持一致,制造透明通道的“假象”。
如果你在Windows系统下用H5浏览器执行本工具,分割后另存为到本地用图片查看器查看,是可以看到透明通道的。
沙发
shanyingwu 发表于 2020-2-16 22:33
3#
3094644 发表于 2020-2-16 22:33
很好 厉害 收藏先
4#
reetin 发表于 2020-2-16 22:43
感谢楼主分享。。
5#
春落秋开 发表于 2020-2-16 22:47
顶起,非常感谢楼主
6#
雪莱鸟 发表于 2020-2-16 22:58
js高手,已保存
7#
谁的坏叔叔 发表于 2020-2-16 23:22
谢谢楼主,辛苦了
8#
飞龙project 发表于 2020-2-16 23:45
感谢楼主,真的很好用!
9#
小小百姓 发表于 2020-2-16 23:52
收藏了,谢谢分享
头像被屏蔽
10#
pywf 发表于 2020-2-17 00:02
提示: 作者被禁止或删除 内容自动屏蔽
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 12:40

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表