banner
AgedCoffee

AgedCoffee

技術筆記

FixedForwardRef#

import React, { forwardRef } from " react";
// 宣告一個適用於
// 泛型組件的類型
type FixedForwardRef = <T, P= {}>(
  render: (props: P, ref: React.Ref<T>)=> React.ReactNode
=> (props: P & React.RefAttributes<T>)=> React.ReactNode;

// 將舊的 forwardRef 轉換為新的
export const fixedForwardRef = forwardRef as FixedForwardRef;

## 漸變 border tailwind 實現

```tsx
export const AnimatedGradientBorderTW: React.FC<{
  children: React.ReactNode
}> = ({ children }) => {
  const boxRef = useRef<HTMLDivElement>(null)

  useEffect(() => {
    const boxElement = boxRef.current

    if (!boxElement) {
      return
    }

    const updateAnimation = () => {
      const angle = (parseFloat(boxElement.style.getPropertyValue('--angle')) + 0.5) % 360
      boxElement.style.setProperty('--angle', `${angle}deg`)
      requestAnimationFrame(updateAnimation)
    }

    requestAnimationFrame(updateAnimation)
  }, [])

  return (
    <div
      ref={boxRef}
      style={
        {
          '--angle': '0deg',
          '--border-color': 'linear-gradient(var(--angle), #070707, #687aff)',
          '--bg-color': 'linear-gradient(#131219, #131219)',
        } as CSSProperties
      }
      className="flex h-[400px] w-[400px] items-center justify-center rounded-lg border-2 border-[#0000] p-3 [background:padding-box_var(--bg-color),border-box_var(--border-color)]"
    >
      {children}
    </div>
  )
}

ios H5 history.back () 返回上一路由 頁面白屏問題#

改變 history.scrollRestoration

使用 history.back 返回上一頁的時候,瀏覽器會記錄頁面的滾動位置,而在 iOS 上面,滾動後返回的時候頁面渲染會出現問題,導致白屏。可以利用 scrollRestoration 屬性,它默認是 auto,也就是會記錄滾動位置(這是 H5 新增的屬性,所以需要判斷瀏覽器是否支持,我實踐的是可以兼容大部分移動端機型)

if ('scrollRestoration' in history) {
  history.scrollRestoration = 'manual' //改為 manual 之後,就不會記錄滾動位置
}

Vite 配置 ws 轉發#

L3PbXs

在螢幕縮放比例發生改變頁面不變的處理方案#

  1. 首頁第一個模組所有的 100vh 全部要動態的改為 calc(100vh * 2)
  2. 視頻的寬度需要調整為 100%(視頻動效會沒)
  3. 登入模態框內部的邏輯調整為 zoom 處理
  • 暫定有問題的動效模組直接不展示
  • 另外注入 URS 模態框的 css 可以區分 Win 還是 Mac

antd-mobile css 變數覆蓋#

:root:root {
  --adm-button-border-radius: 2px;
}

nginx 常規路徑代理配置#

location /docs/zh {
  proxy_pass https://your.domain.com/zh/;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
}

nginx 網段禁止配置#

server {
  listen       80;
  server_name  domain1.com www.domain1.com;
  access_log   logs/domain1.access.log  main;
  root         html;

  deny 61.135.0.0/16;
}

nginx-openresty 查看日誌位置#

rahGOt

Canvas 工具函數#

// 調整圖片的尺寸大小
function imageUrl2ExactCanvas(image: HTMLImageElement, imageSize: LimitImageSize) {
  const cvs = document.createElement('canvas')
  const ctx = cvs.getContext('2d')
  const width = imageSize[0]
  const height = imageSize[1]
  cvs.width = width
  cvs.height = height
  ctx!.drawImage(image, 0, 0, cvs.width, cvs.height)
  image2white(ctx!, width, height)
  return cvs
}

// 圖片透明部分轉換成白色
function image2white(ctx: CanvasRenderingContext2D, width: number, height: number) {
  let imageData = ctx!.getImageData(0, 0, width, height)
  for (let i = 0; i < imageData.data.length; i += 4) {
    // 當該像素是透明的,則設置成白色
    if (imageData.data[i + 3] === 0) {
      imageData.data[i] = 255
      imageData.data[i + 1] = 255
      imageData.data[i + 2] = 255
      imageData.data[i + 3] = 255
    }
  }
  ctx!.putImageData(imageData, 0, 0)
}

/**
 * @param image 圖片
 * @param backType 需要返回的類型blob,file
 * @param quality 圖片壓縮比 0-1,數字越小,圖片壓縮越小
 * @returns
 */
function compressorImage(image: File, backType?: 'blob' | 'file', quality?: number) {
  return new Promise((resolve, reject) => {
    new Compressor(image, {
      quality: quality || 0.8,
      success(result) {
        let file = new File([result], image.name, { type: image.type })

        if (!backType || backType === 'blob') {
          resolve(result)
        } else if (backType === 'file') {
          resolve(file)
        } else {
          resolve(file)
        }
      },
      error(err) {
        reject(err)
      },
    })
  })
}

nginx 配置正則反向代理#

resolver 8.8.8.8;

location ~ /xx/([0-9a-z]+).html {
  proxy_pass http://your.domain/xx/$1/
}

FFmpeg 腳本#

ffmpeg -i video.mp4 -i audio.mp4 -c:v copy -c:a aac -strict experimental output.mp4

在 webpack4 中添加強本地緩存#

const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')

plugins: [
  new HardSourceWebpackPlugin({
    cacheDirectory: path.resolve(__dirname, '../cache'),
  }),
]

在 nextjs 中支持項目外部的.ts,.tsx 文件編譯#

const nextConfig = {
  webpack: (config, options) => {
    config.module.rules.forEach((rule) => {
      if (rule.test && rule.test.toString().includes('tsx|ts')) {
        rule.include = [...rule.include, path.resolve(__dirname, '../common-package/src')]
      }
      if (Array.isArray(rule.oneOf)) {
        rule.oneOf.forEach((rule_inner) => {
          if (rule_inner.test && rule_inner.test.toString().includes('tsx|ts')) {
            rule_inner.include = [
              ...rule_inner.include,
              path.resolve(__dirname, '../common-package/src'),
            ]
          }
        })
      }
    })
    return config
  },
}

H5 的使用技巧#

// 1、捕獲攝像頭,user 表示前置攝像頭,environment 表示後置攝像頭
<input type="file" capture="user" accept="image/*" />

// 2、每 10s 刷新一次
<meta http-equiv="refresh" content="10" />

// 3、開啟 input 輸入框的拼寫檢測
<input type="text" spellcheck="true" lang="en" />

// 4、上傳文件時指定允許的文件格式
<input type="file" accept=".jpeg,.png" />

// 5、阻止瀏覽器翻譯,適用場景比如 Logo 和品牌名
<p translate="no">品牌名稱</p>

// 6、允許選擇多個文件
<input type="file" multiple />

// 7、為 video 標籤添加縮略圖
<video poster="picture.png"></video>

// 8、聲明資源文件的下載
<a href="image.png" download></a>

vite 配合 whistle 跑本地環境的 server-hmr 配置#

server: {
  hmr: {
    protocol: 'ws',
    host: 'localhost',
    },
  },
載入中......
此頁面數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。