资讯专栏INFORMATION COLUMN

如何做一个会liao妹的程序员?

SKYZACK / 868人阅读

摘要:我房租到期了,可以去你心里住吗要是我和你生一个孩子你觉得他会是什么座什么座双子座不,我们的杰作。最后哔哔两句,作为一个程序员,无论工作如何繁忙,请不要忘记撩妹,祝大家早日脱单献上地址

说到撩妹这个话题,估计很多人都觉得和程序员沾不上边,大多数人对程序员的印象是这样的:木讷,老实,内向,不爱社交。眼里只有代码,不懂浪漫!作为一个多年的程序员老砖员,我决定为广大程序员伙伴澄清这个谣言,告诉大家,我们程序员也是很浪漫的!

为了不让大家痛失女神的芳心,我做了一个表白神器,在此和各位程序员小哥哥们分享分享!最终赢取白富美,走上人生巅峰!

首先看看效果。扫描下方二维码即可预览

【看看代码的实现】 一、写代码前首先需要考虑以下几点

兼容不同手机分辨率

采用CSS3动画,更流畅

文字的定位采用一个算法,将其竖排居中显示

后期的可拓展性

二、代码之工具方法

我们需要一些工具方法,将之抽离出来以便公用,最好不要污染业务代码,这里用了一个词“污染”,在我们做项目的时候,其实很多代码都是和业务无关的,如果都写到一起了,这样会让我们的业务非常不清晰,之所以要抽离出来,就是为了让我们的业务逻辑清晰可见,当抽离出来后,你会发现,业务代码就几行,看上去非常的简洁。

以下是我抽离的非业务代码

/**
 *
 * @desc 生成指定范围随机数
 * @param  {Number} min
 * @param  {Number} max
 * @return {Number}
 */
export function randomNum(min, max) {
    return Math.floor(min + Math.random() * (max - min));
}

/**
 * @desc 数组打乱顺序
 */
export function randomArrSort(arr) {
    arr.sort(() => 0.5 - Math.random());
    return arr;
}

/**
 *
 * @desc 随机生成颜色
 * @return {String}
 */
export function randomColor() {
    return "#" + ("00000" + ((Math.random() * 0x1000000) << 0).toString(16)).slice(-6);
}

/**
 * 生成一个用不重复的ID
 */
export function getRandomID(randomLength = 8) {
    return "id_" + Number(
        Math.random()
            .toString()
            .substr(3, randomLength || 8) + Date.now()
    ).toString(36);
}

/**
 * @desc 设置自动适配的尺寸
 */
export function setSize($box, scale, fixed) {
    let width = fixed ? appWidth : $box.width(),
        height = fixed ? appHeight : $box.height();
    const { innerWidth, innerHeight } = window;
    let top = (innerHeight - height * scale) / 2;
    if (top < 0) {
        top = 0;
    }
    $box.css({
        left: (innerWidth - width * scale) / 2,
        top: top,
        transform: `scale(${scale})`
    });
}

/**
 * @desc 计算sacle 和 偏移
 */
export function getScale() {
    const width = 320;
    const height = 514;
    // 自动适配
    const { innerWidth, innerHeight } = window;
    // 假设宽度适配 scale * width = innerWidth
    let scale1 = innerWidth / width;
    // 假设高度适配 scale * height = innerHeigh
    let scale2 = innerHeight / height;
    return scale1 > scale2 ? scale2 : scale1;
}
三、抽取公共类

其实我们的文字可以多带带抽离成一个类进行管理,这个类需要包含文字相关的一些方法

1、获取随机文案
2、获取全部文字
3、渲染全部的文字
4、执行文字动画
5、计算目标文案的位置
6、寻找目标文字的位置,然后clone一个
7、初始化
8、重新执行

我大致评估了,需要这些方法。

所以文字的类构造如下:

import * as tool from "../utils/tools";

import { texts } from "./texts";

/**
 * @desc 文字的方法
 */
export default class Text {
    constructor(set) {
        this.set = Object.assign(
            {
                target: "#phone",
                width: 320,
                height: 514,
                callback: () => {}
            },
            set
        );
        this.dom = $(set.target);
    }

    // 获取随机文案
    getText() {
        const index = tool.randomNum(0, texts.length - 1);
        const t1 = texts[index];
        return t1.split("");
    }

    // 获取全部文字
    getAllText() {
        let all = [];
        const { width, height } = this.set;
        texts.forEach(d => {
            // let str = d.replace(/[,,。,?,!,……,~,:”,“,s]/gm, "");
            all = [...all, ...d.split("")];
        });
        // 去重
        all = Array.from(new Set(all));
        all = all.map(text => {
            const a = tool.randomNum(5, 10);
            const iskey = this.targetText.indexOf(text) === -1 ? false : true;
            return {
                id: tool.getRandomID(),
                y: height / 2 - a / 2,
                x: width / 2 - a / 2,
                opacity: Math.random() * 0.5,
                scale: Math.random() * 1.2,
                iskey,
                width: a,
                height: a,
                text
            };
        });
        return tool.randomArrSort(all);
    }

    // 渲染allText
    renderTexts(arr) {
        let shtml = "";
        arr.forEach(d => {
            const { id, x, y, scale, opacity, iskey, width, height, text } = d;
            shtml += `${text}`;
        });
        this.dom.append(shtml);
    }

    // 计算目标文字的位置
    getTargetCoord(targetText) {
        const tlen = targetText.length;
        let val = 10; // 10个换行
        let size = 20,
            arr = [],
            boxWidth = Math.ceil(tlen / val) * size,
            boxHeight = size * val; // 10个字换行
        const { width, height } = this.set;
        // 坐标起点
        const start = {
            x: (width - boxWidth) / 2,
            y: (height - boxHeight) / 2 - 100
        };
        for (let i = 0; i < tlen; i++) {
            let a = Math.floor(i / val);
            arr.push({
                width: size,
                height: size,
                x: start.x + a * size,
                y: start.y + (i - a * val) * size
            });
        }
        return arr;
    }

    // 找到对应的字,然后clone一个对象
    cloneTargetStyle(d, tArr) {
        const obj = tArr.filter(a => {
            return a.text === d;
        })[0];
        obj.id = tool.getRandomID();
        return { ...obj };
    }

    // 目标文字动画
    targetTextAimate() {
        let index = 0;
        let tArr = [];
        this.allText.forEach(d => {
            if (d.iskey) {
                tArr.push(d);
            }
            $(`#${d.id}`).css({
                opacity: 0
            });
        });

        // 获取目标数组
        const targetArr = [];
        this.targetText.forEach(d => {
            targetArr.push(this.cloneTargetStyle(d, tArr));
        });

        // 设置坐标
        const arr = this.getTargetCoord(targetArr);
        // 渲染dom
        this.renderTexts.bind(this)(targetArr);
        targetArr.forEach((d, index) => {
            let item = arr[index];
            $(`#${d.id}`).css({
                opacity: 1,
                width: item.width,
                height: item.height,
                transform: `translate(${item.x}px, ${item.y}px) scale(1)`
            });
        });

        setTimeout(() => {
            this.set.callback();
        }, 3000);
    }

    // allText 文字动画
    allTextAnimate() {
        const { width, height } = this.set;
        let count = 0;
        const doAnimate = () => {
            count++;
            this.allText = this.allText.map(d => {
                d.y = tool.randomNum(0, height);
                d.x = tool.randomNum(0, width);
                d.scale = Math.random() * 1.5;
                // d.opacity = Math.random() * 0.5;
                return d;
            });
            this.allText.forEach(d => {
                const { x, y, scale } = d;
                $(`#${d.id}`).css({
                    transform: `translate(${x}px, ${y}px) scale(${scale})`
                });
            });
        };
        const runTime = () => {
            if (count > 2) {
                setTimeout(() => {
                    this.targetTextAimate.bind(this)();
                }, 3000);
                return;
            }
            setTimeout(() => {
                doAnimate();
                runTime();
            }, 3000);
        };
        doAnimate();
        runTime();
    }

    // 重新执行
    restart = () => {
        this.dom.empty();
        this.targetText = this.getText();
        this.allText = this.getAllText.bind(this)();
        this.renderTexts.bind(this)(this.allText);
        setTimeout(() => {
            this.allTextAnimate.bind(this)();
        }, 10);
    };

    // 初始化
    init = () => {
        // 获取文案
        this.targetText = this.getText();
        this.allText = this.getAllText.bind(this)();

        // 渲染文字
        this.dom.addClass("h5ds-text7");
        this.renderTexts.bind(this)(this.allText);

        setTimeout(() => {
            this.allTextAnimate.bind(this)();
        }, 0);
    };
}
四、文案拓展性,可自定义文案

为了可以自定义文案,我多带带把文案拿了出来

export const texts = [
    "我想在你那里买一块地。买什么地?买你的死心塌地",
    "你知道你和星星有什么区别吗?星星在天上而你在我心里",
    "我十拿九稳 就只差你一吻了",
    "可爱不是长久之计,可爱我是",
    "小猪佩奇,你配我",
    "有谣言说我喜欢你,我澄清一下,那不是谣言",
    "只许州官放火 不许……你离开我",
    "你昨天晚上应该很累吧,因为你在我梦里一直跑个不停",
    "我觉得你接近我就是在害我,害得我好喜欢你呀",
    "你今天好奇怪,怪可爱的",
    "我觉得我好花心,你每天的样子我都好喜欢",
    "你有打火机嘛?没有?那你是如何点燃我的心的",
    "我说不清我为什么爱你,我只知道,只要有你,我就不可能爱上别人",
    "我喜欢你,像你妈打你,不讲道理",
    "知道你为什么这么冷吗?因为你没有像我这么暖的对象在身边啊。",
    "无事献殷勤,非……非常喜欢你",
    "子曰:三思而后行,1,2,3~嗯~我喜欢你。",
    "小女子不才,掐指一算,公子今生缺我。",
    "你有地图吗?我在你的眼睛里迷路了。",
    "你知道我最喜欢什么神吗?是你的眼神。",
    "你要是丑点,我或许可以带你逛街看电影吃西餐散散步看星星看月亮,从诗词歌赋谈到人生哲学,可你长的那么好看,让我只想和你恋爱。",
    " 我房租到期了,可以去你心里住吗?",
    "“要是我和你生一个孩子你觉得他会是什么座?”“什么座?双子座?”“不,我们的杰作。”",
    "“你可以笑一个吗?”“为什么啊?”“因为我的咖啡忘加糖了。”",
    "“你想喝点什么?”“我想呵护你。”",
    "“我觉得你长得像我一个亲戚。”“???”“我妈的儿媳妇。”",
    "“你知道情人眼里出什么吗?”“西施啊。”“不,出现你。”",
    "“你最近是不是又胖了?”“没有啊,为什么这么说?”“那你为什么在我心里的分量越来越重了呢?”",
    "落叶归根,你归我。",
    "苦海无涯,回头是我。",
    "不想撞南墙了,只想撞撞先生胸膛。",
    "你上辈子一定是碳酸饮料吧,不然我怎么一看到你就开心地冒泡呢。",
    "你会弹钢琴吗?不会?那你是怎么撩动我的心弦的呢。",
    "第一次见到你时,上帝在我耳旁说了几个字,在劫难逃。",
    "你知道喝什么酒最容易醉吗?是你的天长地久。",
    "“你属什么?”“我属虎。”“你不要再骗人了,你属于我。”",
    "“你是什么星座? 双子座吗?”“ 不是。我是为你量身定做。”",
    "你知道我最大的缺点是什么吗?是缺点你。",
    "如果我把你推到花园里面,我就会找不到你。因为你像花儿一样美丽。",
    "有时候生活有些苦难,你不要去抱怨,抱我就好了。"
];
五、业务代码

其实当我们抽离了类,抽取了非业务相关的公共方法。业务代码就非常简单了,下面就是HTML + 业务相关的代码。





    
    
    
    
    
    



    
    
    

`); alert("图片已经生成,长按屏幕保存到手机!") }) .catch(function(error) { console.error("oops, something went wrong!", error); }); }); });
六、总结

在做一个项目的时候,我们尽可能的剥离出业务不相关的代码,让编程的思想尽可能的清晰,任何API接口的设计都是为了让用户更好的实现自己的业务,当然,如果对底层的实现逻辑有兴趣的朋友,也可以去具体的了解下每个方法内部的实现,进一步提升自身的实力,当然,Text这个类还可以进一步的优化,比如把数据作为参数传到类里面,这样做会更灵活!这些就是后来所谓的优化,迭代环节了。

最后哔哔两句,作为一个程序员,无论工作如何繁忙,请不要忘记撩妹,祝大家早日脱单!献上github地址:https://github.com/mtsee/vale...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96945.html

相关文章

  • 给学弟学妹的招聘分享

    摘要:阿里作为的一员,面试是有难度的。原没有那小公司练手,很多同学都是裸考阿里。 这个总结其实来得挺晚的,但是又非常必要。我很有幸参加了今年的春秋招,并且前往深圳和北京这两个城市体验一线城市的精彩和心酸,无论是去深圳的一家小公司,还是转战北京小米。最终签约成都华为。我都有好多话想说。但是今天不是故事会,而是求职分享会,我希望我在本年度春秋招的所见所得能帮助你们应对明年的招聘 接下来请看一个时...

    blair 评论0 收藏0
  • Python中的描述符

    摘要:解答三个问题,描述是什么如何实现使用场景一什么是描述符描述符就是一个具有绑定行为的对象属性,其属性访问将由描述符协议中的方法覆盖。如果这些方法中的任何一个针对某个对象定义,那么它就被认为是一个描述符。 解答三个问题,描述是什么?如何实现?使用场景? 一、什么是描述符 描述符就是一个具有绑定行为的对象属性,其属性访问将由描述符协议中的方法覆盖。这些方法为 __get__、__set__ ...

    Aomine 评论0 收藏0

发表评论

0条评论

SKYZACK

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<