前端恶趣味:我吸了juejin首页,好爽!

有位古人说过,人不是在烦的路上,就是正在烦!

最近在逛某乎,总是会刷到很多让人焦虑的话题!比如这样:

或者这样:

还有这样:

然后,就这么一焦虑,我就不怀好意的把目光转向了juejin,要不要把juejin砸了,让面向搜索编程者没有地儿找,少一些竞争者?

首先引入脑海的是二向箔,作为"吾主"最强大武器之一,我打算用这个收了juejin首页!

说干就干!建个demo,打个样品:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Add Span to Each Character</title>
</head>
<body style="background-color: #fff;">
  <!-- Your HTML content here -->
  <p>This is some text.</p>
  <div>
    <p>More text here.</p>
    <image src="./3333.png" />
    <video></video>
  </div>
  <img src="./3333.png" />
  <style>
    .aaa {
      height: 100px;
    }
  </style>
</body>
</html>

再来一段JS,用来模拟一根棍进入效果:

js 复制代码
<script>
    'use strict';
    const targetNodeObject = document.body;
    const styleElement = document.createElement('style');
    const floatBall = document.createElement('div');
    let center = { centerX: 0, centerY: 0 };
    const timer = 32;
    styleElement.textContent = `
          .highlighted-text {
            width: 4px;
            height: 4px;
            margin: 0 2px;
            display: inline-block;
            overflow: hidden;
            background-color: #f00;
            transition: all 1s;
          }
          .highlighted-image {
            margin: 0 2px !important;
            display: inline-block !important;
            overflow: hidden !important;
            background-color: #000 !important;
            transition: all 1s;
            transform-origin: center top;
          }
          .floating-ball {
            width: 4px;
            position:fixed;
            height: 100px;
            background: #000 !important;
            animation: floatAnimation 0.2s linear infinite;
            left: 50%;
            top: -800px;
            transition: top 1s ease;
            z-index:9999;
            border:1px solid #fff;
            transform-origin: center center;
          }
          @keyframes floatAnimation {
            to {
              transform: rotate(360deg);
            }
          }
          .inhaleAnimation{
            position: fixed;
            z-index:9999;
            animation: inhaleAnimation 2s ease-out forwards;
          }
          @keyframes inhaleAnimation {
            to {
              transform: scale(0);
            }
          }
        `;
    document.head.appendChild(styleElement);

    createAttack();
    
    // 创建进攻武器 - 棍
    function createAttack(callback) {
      floatBall.classList.add('floating-ball');
      targetNodeObject.appendChild(floatBall);
      setTimeout(() => {
        floatBall.style.top = "100px";
        setTimeout(() => {
          if (callback) callback();
        }, 1000)
      }, 100)
    }
</script>

大致效果是这样:

好了,第一步完成,接下去想攻击效果,基本思路就是模拟二向箔。二向箔是三维物体二维化,那我们juejin首页是二维物体,那我就一维化。效果就是文字化层点。图片变成线。

完整代码如下:

js 复制代码
  <script>
    'use strict';
    const targetNodeObject = document.body;
    const styleElement = document.createElement('style');
    const floatBall = document.createElement('div');
    let center = { centerX: 0, centerY: 0 };
    const timer = 32;
    styleElement.textContent = `
          .highlighted-text {
            width: 4px;
            height: 4px;
            margin: 0 2px;
            display: inline-block;
            overflow: hidden;
            background-color: #f00;
            transition: all 1s;
          }
          .highlighted-image {
            margin: 0 2px !important;
            display: inline-block !important;
            overflow: hidden !important;
            background-color: #000 !important;
            transition: all 1s;
            transform-origin: center top;
          }
          .floating-ball {
            width: 4px;
            position:fixed;
            height: 100px;
            background: #000 !important;
            animation: floatAnimation 0.2s linear infinite;
            left: 50%;
            top: -800px;
            transition: top 1s ease;
            z-index:9999;
            border:1px solid #fff;
            transform-origin: center center;
          }
          @keyframes floatAnimation {
            to {
              transform: rotate(360deg);
            }
          }
          .inhaleAnimation{
            position: fixed;
            z-index:9999;
            animation: inhaleAnimation 2s ease-out forwards;
          }
          @keyframes inhaleAnimation {
            to {
              transform: scale(0);
            }
          }
        `;
    document.head.appendChild(styleElement);



    function createBall(callback) {
      floatBall.classList.add('floating-ball');
      targetNodeObject.appendChild(floatBall);
      setTimeout(() => {
        floatBall.style.top = "100px";
        setTimeout(() => {
          if (callback) callback();
        }, 1000)
      }, 100)
    }
    createBall(() => {
      init();
      center = getElementCenter(floatBall);
    });
    // 获取棍的中心点位置
    function getElementCenter(element) {
      const rect = element.getBoundingClientRect();
      const centerX = rect.left + rect.width / 2;
      const centerY = rect.top + rect.height / 2;

      return { centerX, centerY }
    }
    
    function init() {
      const steps = [];
      const elements = [];

    // 获取当前信息
      function getNodes(element) {
        const textNodes = [];
        const imageNodes = [];

        function traverse(node) {
          hasBackgroundColor(node)
          if (node.nodeType === Node.TEXT_NODE && node.nodeValue.trim() !== '') {
            textNodes.push(node);
          } else if (isImageNode(node)) {
            imageNodes.push(node);
          } else if (node.nodeType === Node.ELEMENT_NODE && !isExcludedNode(node)) {
            for (const childNode of node.childNodes) {
              traverse(childNode);
            }
          }
        }

        function isExcludedNode(node) {
          const excludedTags = ['SCRIPT', 'STYLE', 'LINK', 'IFRAME', 'path'];
          return excludedTags.includes(node.tagName);
        }

// 校验元素是否有背景颜色
        function hasBackgroundColor(node) {
          try {
            const computedStyle = window.getComputedStyle(node);
            const backgroundColor = computedStyle.backgroundColor;
            if (backgroundColor !== 'rgba(0, 0, 0, 0)' && backgroundColor !== 'transparent') {
              node.style.backgroundColor = 'rgba(255, 255, 255, 1)'
            }
          } catch (e) {
          }
        }

        traverse(element);
        return { textNodes, imageNodes };
      }

        // 添加步骤到执行队列
      function addStep(func, node) {
        steps.push(func.bind(this));
        elements.push(node);
      }
      // 开始步骤
      function startStep() {
        const interTimer = setInterval(() => {
          if (steps.length > 0) {
            const func = steps.shift();
            const element = elements.shift();
            if (func) {
              func();
              if (element) {
                const rect = element.getBoundingClientRect();
                element.style.top = `${rect.top}px`;
                element.style.left = `${rect.left}px`;
                addStep(() => {
                  element.classList.add('inhaleAnimation');
                  element.style.top = `${center.centerY}px`;
                  element.style.left = `${center.centerX}px`;
                  element.addEventListener('animationend', function () {
                    element.remove();
                  });
                })
              }
            }
          } else {
            clearInterval(interTimer);
          }
        }, timer)
      }
      
      const { textNodes, imageNodes } = getNodes(targetNodeObject);
      // 处理文字
      function textFn(node) {
        const textContent = node.nodeValue.trim();
        const newSpan = document.createElement('span');
        const newContent = Array.from(textContent).map(char => {
          const charSpan = document.createElement('span');
          charSpan.textContent = char;
          addStep(() => {
            charSpan.classList.add("highlighted-text");
          }, charSpan);
          newSpan.appendChild(charSpan);
          return charSpan.outerHTML;
        }).join('');
        node.parentNode.replaceChild(newSpan, node);
      };
      // 处理图片
      function imageFn(node) {
        const charSpan = document.createElement('span');
        node.classList.add("highlighted-image");
        addStep(() => {
          const rect = node.getBoundingClientRect();
          charSpan.style.width = `${node.width || node.clientWidth || rect.width}px`;
          charSpan.style.height = `${node.height || node.clientHeight || rect.width}px`;
          charSpan.classList.add("highlighted-image");
          node.replaceWith(charSpan);
          addStep(() => {
            charSpan.style.width = "4px";
            //charSpan.style.transform = `scale(1) rotate(${30}deg)`
          }, charSpan);
        });
      }
      textNodes.forEach(node => {
        if (node.nodeValue.indexOf('@font-face') !== -1) { return; }
        textFn(node);
      });
      imageNodes.forEach(node => {
        imageFn(node);
      });
      
    // 判断是否为图片
    function isImageNode(node) {
      if (node.tagName === 'BODY') { return; }
      const imageTags = ['IMG', 'IMAGE', 'VIDEO', 'svg', "FORM", "svg"];
      return imageTags.includes(node.tagName) &&
        !(node.tagName === 'BODY' && node.classList.contains('floating'));
    }

      startStep();
    }
  </script>

效果为:

效果好像还不错!

现在,将上面JS代码压缩

通过在url输入框内,输入Javascrip:【上面压缩的代码】

将代码放入juejin某页,一起look下效果(截取一段):

看到这里的朋友也知道,这个也就一个前端佬的自嗨了。

但还是想说....

相关推荐
你挚爱的强哥12 分钟前
✅✅✅【Vue.js】sd.js基于jQuery Ajax最新原生完整版for凯哥API版本
javascript·vue.js·jquery
y先森1 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy1 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189111 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿2 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡3 小时前
commitlint校验git提交信息
前端
虾球xz3 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇3 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒4 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员4 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js