Giter Site home page Giter Site logo

helloworld's People

Contributors

jiafeng123 avatar

Watchers

 avatar

helloworld's Issues

contenteditable

<template>
  <div class="ipas-container">
    <div class="left-view">
      <div
        id="textInput"
        ref="textInputRef"
        class="container-left-input"
        :contenteditable="true"
        @input="handleInput"
      >
      </div>
    </div>
    <div class="right-view"></div>
  </div>
</template>
<script lang="ts" setup>
  import { ref, onMounted, nextTick } from 'vue'
  import { cloneDeep,debounce } from 'lodash'
  const textInputRef = ref()
  const str = '\n【Simple Installation】: Telescope dovetail mounting plate, easy to replace and install within seconds, no complicated tools needed.\n【Type】: Telescope Dovetail Mounting Plate with m6 screw Replacement.\n【Material】: The dovetail mounting fixing plate is made of premium aluminum alloy material, wear resistant and durable, has good performance.\n【Multi Use】: This standard dovetail plate can be used to modify astronomical telescopes, connect to different equatorial mounts or add SLR, guide mirrors and other equipment to use.\n【Replacement 】: Directly replaces your worn, cracked, broken and unusable rail bar mounting plate.\nManufacturer: balikha\nASIN: B0CC9FXTP7\nDate First Available: July 19, 2023\nManufacturer: balikha\nASIN: B0CC9FXTP7\nDate First Available: July 19, 2023'
  const offsetsData = [
    {
      "from": "text",
      "origin_word": "Dovetail",
      "offset": 34,
      "length": 8
    },
    {
      "from": "text",
      "origin_word": "Dovetail",
      "offset": 150,
      "length": 8
    },
    {
      "from": "text",
      "origin_word": "Dovetail",
      "offset": 217,
      "length": 8
    },
    {
      "from": "text",
      "origin_word": "Dovetail",
      "offset": 369,
      "length": 8
    }
  ]
  const render = () => {
    let html = ``
    for (let i = 0; i < offsetsData.length; i++) {
      // 处理第一个
      if (i === 0) {
        html += str.slice(0, offsetsData[i].offset)
        html += `<span class="highlight">${str.slice(offsetsData[i].offset, offsetsData[i].offset + offsetsData[i].length)}</span>`
      }
      else {
        html += str.slice(offsetsData[i - 1].offset + offsetsData[i - 1].length, offsetsData[i].offset)
        html += `<span class="highlight">${str.slice(offsetsData[i].offset, offsetsData[i].offset + offsetsData[i].length)}</span>`
      }
      if (i === offsetsData.length - 1) {
        html += str.slice(offsetsData[i].offset + offsetsData[i].length)
      }
    }
    // 渲染
    html = html.replace(/\n/g, '<br/>')
    textInputRef.value.innerHTML = html
  }
  onMounted(() => {
    nextTick(() => {
      render()
    })
  })
  function getCursorPosition(parent: any, node: any, offset: any, stat: any) {
    if (stat.done) return stat;
    let currentNode = null;
    if (parent.childNodes.length === 0) {
      stat.pos += parent.textContent.length;
    } else {
      for (let i = 0; i < parent.childNodes.length && !stat.done; i++) {
        currentNode = parent.childNodes[i];
        if (currentNode === node) {
          stat.pos += offset;
          stat.done = true;
          return stat;
        } getCursorPosition(currentNode, node, offset, stat);
      }
    }
    return stat;
  }
  function setCursorPosition(parent: any, range: any, stat: any) {
    if (stat.done) return range;
    let currentNode = null;
    if (parent.childNodes.length === 0) {
      if (parent.textContent.length >= stat.pos) {
        range.setStart(parent, stat.pos);
        stat.done = true;
      } else {
        stat.pos -= parent.textContent.length;
      }
    } else {
      for (let i = 0; i < parent.childNodes.length && !stat.done; i++) {
        currentNode = parent.childNodes[i];
        setCursorPosition(currentNode, range, stat);
      }
    }
    return range;
  }
  function resetCursor(sel: any, pos: any) {
    // restore the position
    sel.removeAllRanges();
    const range = setCursorPosition(textInputRef.value, document.createRange(), {
      pos: pos.pos,
      done: false,
    });
    range.collapse(true);
    sel.addRange(range);
  }
  const handleInput = debounce(() => {
    const sel = window.getSelection() as Selection;
    const node = sel.focusNode;
    const offset = sel.focusOffset;
    const pos = getCursorPosition(textInputRef.value, node, offset, { pos: 0, done: false });
    if (offset === 0) pos.pos += 0.5;
    // 记录上次匹配的数据,用内容去匹配
    const cloneData = cloneDeep(offsetsData)
    let matchedData = cloneData.map(i => i.origin_word.toLowerCase())
    // 去重
    matchedData = Array.from(new Set(matchedData))
    // 编辑之后,重新渲染
    let html = textInputRef.value.innerHTML
    // 去掉所有的span,包括class="highlight"和不包括class="highlight"
    html = html.replaceAll(/<span[^>]*>([^<]*)<\/span>/g, '$1')
    html = html.replaceAll(/<span[^>]*>([^<]*)<\/span>/g, '$1')
    for (let i = 0; i < matchedData.length; i++) {
      const reg = new RegExp(matchedData[i], 'gi')
      html = html.replaceAll(reg, `<span class="highlight">${matchedData[i]}</span>`)
    }
    textInputRef.value.innerHTML = html
    resetCursor(sel, pos)
  },200)
</script>
<style>
  .highlight {
    padding: 2px;
    border-radius: 2px;
    background-color: #FFD700;
  }
</style>
<style lang="less" scoped>
  .ipas-container {
    background-color: #fff;
    height: 100%;
    display: flex;
    .left-view {
      flex: 1;
      padding: 32px 40px;
      display: flex;
      justify-content: center;
      align-items: center;
      // background-color: #F7F8FA;
      #textInput {
        width: 80%;
        height: 80%;
        margin: auto;
        outline: none;
        border-radius: 8px;
        overflow-y: auto;
        padding: 12px;
        line-height: 30px;
        background: var(---color-fill-1, #F7F8FA);
        word-break: normal;
      }
    }
    .right-view {
      width: 840px;
      padding: 32px 40px;
    }
  }
  @media screen and (max-width: 1280px) {
    .right-view {
      width: 520px;
    }
  }
  @media screen and (max-width: 1440px) {
    .right-view {
      width: 600px;
    }
  }
</style>

svg animation

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Handwritten Signature Animation</title>
    <style>
      body {
        display: flex;
        justify-content: center;
        align-items: center;
        height: 100vh;
        background-color: #f0f0f0;
      }

      .signature-container {
        width: 500px;
        height: 200px;
      }

      svg {
        width: 100%;
        height: 100%;
      }

      path {
        fill: none;
        stroke: #000;
        stroke-width: 2;
        stroke-dasharray: 1000;
        stroke-dashoffset: 1000;
        animation: draw 4s ease-in-out forwards;
      }

      @keyframes draw {
        to {
          stroke-dashoffset: 0;
        }
      }
    </style>
  </head>
  <body>
    <div class="signature-container">
      <svg viewBox="0 0 500 200">
        <path
          id="signature-path"
          d="M20,80 Q40,10 60,80 T100,80 Q140,10 160,80 T200,80"
        />
      </svg>
    </div>
    <script>
            // script.js
      document.addEventListener('DOMContentLoaded', () => {
        const path = document.getElementById('signature-path');
        const length = path.getTotalLength();

        path.style.strokeDasharray = length;
        path.style.strokeDashoffset = length;
      });
    </script>
  </body>
</html>

canvas粒子效果

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas Particle Background</title>
<style>
  body, html {
    margin: 0;
    padding: 0;
    overflow: hidden;
    background: #000;
  }
</style>
</head>
<body>
<canvas id="particleCanvas"></canvas>
<script>
  const canvas = document.getElementById('particleCanvas');
  const ctx = canvas.getContext('2d');
  let particles = [];

  function resizeCanvas() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
  }

  window.addEventListener('resize', resizeCanvas);
  resizeCanvas();

  class Particle {
    constructor() {
      this.reset();
    }

    reset() {
      this.x = Math.random() * canvas.width;
      this.y = Math.random() * canvas.height;
      this.size = Math.random() * 3 + 1;
      this.speedX = Math.random() * 2 - 1;
      this.speedY = Math.random() * 2 - 1;
      this.color = `rgba(255, 255, 255, ${Math.random()})`;
    }

    update() {
      this.x += this.speedX;
      this.y += this.speedY;

      if (this.x < 0 || this.x > canvas.width || this.y < 0 || this.y > canvas.height) {
        this.reset();
      }
    }

    draw() {
      ctx.fillStyle = this.color;
      ctx.beginPath();
      ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
      ctx.closePath();
      ctx.fill();
    }
  }

  function createParticles(count) {
    for (let i = 0; i < count; i++) {
      particles.push(new Particle());
    }
  }

  function animate() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    particles.forEach(particle => {
      particle.update();
      particle.draw();
    });

    requestAnimationFrame(animate);
  }

  createParticles(100);
  animate();
</script>
</body>
</html>

文本标记

var element = {
    "text": "The blood pressure was initially elevated on the patient's outpatient medications, so his hypertension medicines were adjusted by increasing his lisinopril to 20 mg qd."
  },
  rawText = element.text.slice(),
  spans = [{
    "begin": 145,
    "end": 155,
    "tooltip": "section 1"
  }, {
    "begin": 4,
    "end": 18,
    "tooltip": "section 2"
  }, {
    "begin": 4,
    "end": 18,
    "tooltip": "section 3"
  }, {
    "begin": 90,
    "end": 102,
    "tooltip": "section 4"
  }, {
    "begin": 4,
    "end": 41,
    "tooltip": "section 5"
  }];

var highlightedString = createHighlightedString(spans,element.text);
document.getElementById('text').innerHTML = highlightedString;


function createHighlightedString(ranges, text) {
  var flatRanges = flattenRanges(ranges);
  var inflatedRanges = inflateRanges(flatRanges, text.length);
  var filledRanges = fillRanges(inflatedRanges, text);
  var str = "";
  var index = 0;
  console.log('===============', filledRanges)
  for (var i in filledRanges) {
    var range = filledRanges[i];
    var begin = range.begin, end = range.end;
    if (range.count > 0) {
      if (range.tooltip) {
        str += "<span class='highlight-" + range.count + " tooltip'>" + range.text + "<span class='tooltiptext tooltip-bottom'>" + range.tooltip.join('<br/>') + "</span></span>";
      } else {
        str += "<span class='highlight-" + range.count + "'>" + range.text + "</span>";
      }
    } else {
      str += range.text;
    }
  }
  return str;
}

function flattenRanges(ranges) {
  var points = [];
  var flattened = [];
  for (var i in ranges) {
    if (ranges[i].end < ranges[i].begin) { //RE-ORDER THIS ITEM (BEGIN/END)
      var tmp = ranges[i].end; //RE-ORDER BY SWAPPING
      ranges[i].end = ranges[i].begin;
      ranges[i].begin = tmp;
    }
    points.push(ranges[i].begin);
    points.push(ranges[i].end);
  }
  //MAKE SURE OUR LIST OF POINTS IS IN ORDER
  points.sort(function(a, b){return a-b});
  //FIND THE INTERSECTING SPANS FOR EACH PAIR OF POINTS (IF ANY)
  //ALSO MERGE THE ATTRIBUTES OF EACH INTERSECTING SPAN, AND INCREASE THE COUNT FOR EACH INTERSECTION
  for (var i in points) {
    if (i==0 || points[i]==points[i-1]) continue;
    var includedRanges = ranges.filter(function(x){
      return (Math.max(x.begin,points[i-1]) < Math.min(x.end,points[i]));
    });
    if (includedRanges.length > 0) {
      var flattenedRange = {
        begin:points[i-1],
        end:points[i],
        count:0
      }
      for (var j in includedRanges) {
        var includedRange = includedRanges[j];
        for (var prop in includedRange) {
          if (prop != 'begin' && prop != 'end') {
            if (!flattenedRange[prop]) flattenedRange[prop] = [];
            flattenedRange[prop].push(includedRange[prop]);
          }
        }
        flattenedRange.count++;
      }
      flattened.push(flattenedRange);
    }
  }
  return flattened;
}

function inflateRanges(ranges, length=0) {
  var inflated = [];
  var lastIndex;
  for (var i in ranges) {
    if (i==0) {
      //IF THERE IS EMPTY TEXT IN THE BEGINNING, CREATE AN EMOTY RANGE
      if (ranges[i].begin > 0){
        inflated.push({
          begin:0,
          end:ranges[i].begin-1,
          count:0
        });
      }
      inflated.push(ranges[i]);
    } else {
      if (ranges[i].begin == ranges[i-1].end) {
        ranges[i-1].end--;
      }
      if (ranges[i].begin - ranges[i-1].end > 1) {
        inflated.push({
          begin:ranges[i-1].end+1,
          end:ranges[i].begin-1,
          count:0
        });
      }
      inflated.push(ranges[i]);
    }
    lastIndex = ranges[i].end;
  }
  //FOR SIMPLICITY, ADD ANY REMAINING TEXT AS AN EMPTY RANGE
  if (lastIndex+1 < length-1) {
    inflated.push({
      begin:lastIndex+1,
      end:length-1,
      count:0
    })
  }
  return inflated;
}

function fillRanges(ranges, text) {
  for (var i in ranges) {
    ranges[i].text = text.slice(ranges[i].begin,ranges[i].end+1);
  }
  return ranges;
}

平滑动画绘制形状

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Smooth Canvas Star Drawing Animation</title>
<style>
  body, html {
    margin: 0;
    padding: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    background: #000;
  }
  canvas {
    border: 1px solid #fff;
  }
</style>
</head>
<body>
<canvas id="starCanvas" width="600" height="600"></canvas>
<script>
  const canvas = document.getElementById('starCanvas');
  const ctx = canvas.getContext('2d');
  const centerX = canvas.width / 2;
  const centerY = canvas.height / 2;
  const outerRadius = 200;
  const innerRadius = 80;
  const points = 5;
  const totalSteps = 500; // 动画的总步数
  let currentStep = 0;

  function drawStar(cx, cy, outerR, innerR, n, step) {
    ctx.beginPath();
    let progress = step / totalSteps;
    let maxIndex = Math.floor(progress * n * 2);
    let remainingProgress = (progress * n * 2) - maxIndex;

    for (let i = 0; i <= maxIndex; i++) {
      const angle = i * Math.PI / n;
      const radius = (i % 2 === 0) ? outerR : innerR;
      const x = cx + radius * Math.cos(angle);
      const y = cy + radius * Math.sin(angle);
      if (i === 0) {
        ctx.moveTo(x, y);
      } else {
        ctx.lineTo(x, y);
      }
    }

    if (remainingProgress > 0 && maxIndex < n * 2) {
      const angle = (maxIndex + 1) * Math.PI / n;
      const radius = ((maxIndex + 1) % 2 === 0) ? outerR : innerR;
      const x = cx + radius * Math.cos(angle);
      const y = cy + radius * Math.sin(angle);

      const prevAngle = maxIndex * Math.PI / n;
      const prevRadius = (maxIndex % 2 === 0) ? outerR : innerR;
      const prevX = cx + prevRadius * Math.cos(prevAngle);
      const prevY = cy + prevRadius * Math.sin(prevAngle);

      const interpolatedX = prevX + (x - prevX) * remainingProgress;
      const interpolatedY = prevY + (y - prevY) * remainingProgress;
      ctx.lineTo(interpolatedX, interpolatedY);
    }

    ctx.strokeStyle = '#fff';
    ctx.lineWidth = 2;
    ctx.stroke();
  }

  function animate() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    drawStar(centerX, centerY, outerRadius, innerRadius, points, currentStep);
    currentStep++;
    if (currentStep <= totalSteps) {
      requestAnimationFrame(animate);
    }
  }

  animate();
</script>
</body>
</html>

手机端tabs

<template>
  <section class="carousel_wrapper">
    <a-carousel
      auto-play
      indicator-type="line"
      style="height: 480px;"
      @change="handleChange"
    >
      <a-carousel-item
        v-for="image,i of carouselData"
        :key="i"
      >
        <section class=" relative h-full">
          <img
            :src="image.img"
            class="h-full w-full object-cover"
          >
          <section class="absolute left-[134px] 2xl:top-[134px] xl:top-28 lg:top-16 max-lg:top-12 Djinbu flex flex-col items-start">
            <p
              class="text-[#1A3471] 2xl:text-3xl xl:text-[26px] lg:text-2xl max-lg:text-2xl"
              :class="{
                '!text-white': i == 1
              }"
            >
              {{ image.title1 }}
            </p>
            <p
              class="text-[#1A3471] 2xl:text-7xl mt-4 max-lg:mt-2 xl:text-6xl lg:text-5xl max-lg:text-4xl"
              :class="{
                '!text-white': i == 1
              }"
            >
              {{ image.title2 }}
            </p>
            <p
              v-if="i == 1"
              class=" !text-white text-sm fontSC 2xl:mt-9 xl:mt-8 lg:mt-7 max-lg:mt-4"
            >
              领域:多模态大模型 / 数据采集 / NLP / CV
            </p>
            <section
              :class="{
                ' !bg-white/15 !text-white hover:!bg-white/30': i == 1
              }"
              class="2xl:mt-20 xl:mt-12 lg:mt-10 max-lg:mt-6 py-2 cursor-pointer transition-all hover:bg-[#57A9FB] text-white text-sm fontSC px-5 gap-2 flex justify-center items-center rounded-lg bg-[#3491FA] backdrop-blur-[2px]"
            >
              <svg
                xmlns="http://www.w3.org/2000/svg"
                width="14"
                height="14"
                viewBox="0 0 14 14"
                fill="none"
              >
                <path
                  fill-rule="evenodd"
                  clip-rule="evenodd"
                  d="M10.3906 6.41627L7.67475 3.70038L8.4997 2.87542L12.6245 7.00021L8.4997 11.125L7.67475 10.3L10.3918 7.58294L1.45825 7.58294L1.45825 6.41627L10.3906 6.41627Z"
                  fill="white"
                />
              </svg>
              <span>查看全部赛题</span>
            </section>
          </section>
        </section>
      </a-carousel-item>
    </a-carousel>
    <section
      id="test-tabs"
      class="flex gap-4 overflow-x-auto test-tabs"
    >
      <div
        v-for="i of 20"
        :key="i"
        class="flex flex-shrink-0 items-center justify-center w-16 h-16 bg-[#E6E6E6] rounded-lg"
      >
        {{ i }}
      </div>
    </section>
  </section>
</template>

<script setup lang="ts">
  import img1 from '@/assets/images/banner1.png'
  import img2 from '@/assets/images/banner2.png'
  const images = [
    img1,
    img2,
  ];
  const carouselData = ref([
    {
      title1: '第一届上海交大-三态',
      title2: '跨境电商 AI 全球挑战赛',
      img: img1
    },
    {
      title1: '枪械零件识别:',
      title2: '这个零件可以用在枪上吗?',
      img: img2
    },
  ])
  const handleChange=(value)=>{
  }
  onMounted(() => {
    nextTick(() => {
      const scrollableDiv = document.getElementById('test-tabs');
      let isDown = false;
      let startX;
      let scrollLeft;

      scrollableDiv.addEventListener('mousedown', (e) => {
        isDown = true;
        startX = e.pageX - scrollableDiv.offsetLeft;
        scrollLeft = scrollableDiv.scrollLeft;
      });

      scrollableDiv.addEventListener('mousemove', (e) => {
        if (!isDown) return;
        e.preventDefault();
        const x = e.pageX - scrollableDiv.offsetLeft;
        const walk = (x - startX) * 3;
        scrollableDiv.scrollLeft = scrollLeft - walk;
      });

      scrollableDiv.addEventListener('mouseup', () => {
        isDown = false;
      });

      scrollableDiv.addEventListener('mouseleave', () => {
        isDown = false;
      });

      scrollableDiv.addEventListener('touchstart', (e) => {
        isDown = true;
        startX = e.touches[0].pageX - scrollableDiv.offsetLeft;
        scrollLeft = scrollableDiv.scrollLeft;
      });

      scrollableDiv.addEventListener('touchmove', (e) => {
        if (!isDown) return;
        e.preventDefault();
        const x = e.touches[0].pageX - scrollableDiv.offsetLeft;
        const walk = (x - startX) * 3;
        scrollableDiv.scrollLeft = scrollLeft - walk;
      });

      scrollableDiv.addEventListener('touchend', () => {
        isDown = false;
      });
      setTimeout(() => {
        const tab = document.querySelector('.test-tabs > div:nth-child(10)');
        tab.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });
      }, 3000);
    })
  })
</script>
<style scoped lang="less">
@media screen and (min-width: 1536px)  {
  .carousel_wrapper{
    :deep(.arco-carousel){
      height: 480px !important;
    }
  }
}
@media screen and (max-width: 1536px) and (min-width: 1280px)  {
  .carousel_wrapper{
    :deep(.arco-carousel){
      height: 400px !important;
    }
  }
}
@media screen and (max-width: 1280px) and (min-width: 1024px) {
  .carousel_wrapper{
    :deep(.arco-carousel){
      height: 320px !important;
    }
  }
}
@media screen and (max-width: 1024px) {
  .carousel_wrapper{
    :deep(.arco-carousel){
      height: 240px !important;
    }
  }
}
:deep(.arco-carousel-indicator-item){
  background-color: #fff;
  opacity: 0.25;
  width: 30px;
}
:deep(.arco-carousel-indicator-item-active){
  opacity: 0.4;
}
.carousel_wrapper:has(.arco-carousel-slide div:first-child.arco-carousel-item-current){
  :deep(.arco-carousel-indicator-item){
    background-color: #57A9FB;
    opacity: 0.25;
    width: 30px;
  }
  :deep(.arco-carousel-indicator-item-active){
    opacity: 0.6;
  }
}
:deep(.arco-carousel-arrow > div > svg){
  font-size: 3rem;
  stroke: rgba(255, 255, 255, 0.6);
}
:deep(.arco-carousel-arrow-left),:deep(.arco-carousel-arrow-right){
  background-color: transparent;
  width: 3rem;
  height: 3rem;
  &:hover{
    background-color: transparent;
    svg{
      transition: all 0.3s ease-in-out;
      stroke: rgba(255, 255, 255, 0.85);
    }
  }
}

// 隐藏滚动条
::-webkit-scrollbar {
  display: none;
}
.test-tabs{
  -webkit-overflow-scrolling: touch;
  cursor: pointer;
  scroll-snap-type: x mandatory;
}
</style>

切换黑色主题动画

const toggleTheme = useToggle(isDark)
const handleToggleTheme = (event: MouseEvent) => {
  console.log(event)

  const x = event.clientX
  const y = event.clientY
  const { innerWidth, innerHeight } = window
  const endRadius = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y))
  // @ts-expect-error: Transition API
  if (!document.startViewTransition) {
    toggleTheme()
    return
  }
  // @ts-expect-error: Transition API
  const transition = document.startViewTransition(() => {
    toggleTheme()
  })
  transition.ready.then(() => {
    const clipPath = [`circle(0px at ${x}px ${y}px)`, `circle(${endRadius}px at ${x}px ${y}px)`]
    document.documentElement.animate(
      {
        clipPath: theme.value === 'dark' ? clipPath : [...clipPath].reverse()
      },
      {
        duration: 300,
        easing: 'ease-in',
        pseudoElement: theme.value === 'dark' ? '::view-transition-new(root)' : '::view-transition-old(root)'
      }
    )
  })

}

相似度计算

  const calculateSimilarity = (str1:string, str2:string) => {
    const len1 = str1.length;
    const len2 = str2.length;

    // 创建一个矩阵,其中单元格 (i, j) 存储将 str1[0...i-1] 转换为 str2[0...j-1] 的最小编辑距离
    const matrix = new Array(len1 + 1).fill(null).map(() => new Array(len2 + 1).fill(0));

    // 初始化第一行和第一列
    for (let i = 0; i <= len1; i++) {
      matrix[i][0] = i;
    }
    for (let j = 0; j <= len2; j++) {
      matrix[0][j] = j;
    }

    // 填充矩阵
    for (let i = 1; i <= len1; i++) {
      for (let j = 1; j <= len2; j++) {
        const cost = str1[i - 1] === str2[j - 1] ? 0 : 1;
        matrix[i][j] = Math.min(
          matrix[i - 1][j] + 1, // 删除
          matrix[i][j - 1] + 1, // 插入
          matrix[i - 1][j - 1] + cost // 替换
        );
      }
    }

    // 返回矩阵的右下角单元格,即两个字符串之间的 Levenshtein 距离
    return matrix[len1][len2];
  }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.