js+贝塞尔曲线+animate动画

news2024/11/17 3:44:13

文章目录

  • 一 介绍
  • 二 示例
    • 1阶贝塞尔曲线
    • 2阶贝塞尔曲线
    • 3阶贝塞尔曲线:
    • 4/n阶贝塞尔曲线
  • 三 封装和使用
    • bezier.js
    • App.jsx
    • App.scss

一 介绍

贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。

下面是我们最常用到bezier曲线的地方

  • svg
  • canvas/webgl
  • css3 动画
  • animation

下面我们将用js来实现贝塞尔曲线的画制

通用的贝塞尔曲线公式:
贝塞尔曲线公式
由此公式可计算得到下面的n阶贝塞尔曲线各个坐标点

二 示例

1阶贝塞尔曲线

    /**
     * @desc 一阶贝塞尔
     * @param {number} t 当前百分比
     * @param {Array} p1 起点坐标
     * @param {Array} p2 终点坐标
     */
    oneBezier(t, p1, p2) {
        const [x1, y1] = p1;
        const [x2, y2] = p2;
        let x = x1 + (x2 - x1) * t;
        let y = y1 + (y2 - y1) * t;
        return [x, y];
    }

1阶贝塞尔曲线:
上图为1阶贝塞尔的绘制,其实只是从起点(-17,285)到终点(1920,89)的直线运动,中间并没有改变运动轨迹

2阶贝塞尔曲线

在这里插入图片描述

    /**
     * @desc 二阶贝塞尔
     * @param {number} t 当前百分比
     * @param {Array} p1 起点坐标
     * @param {Array} p2 终点坐标
     * @param {Array} cp 控制点
     */
    twoBezier(t, p1, cp, p2) {
        const [x1, y1] = p1;
        const [cx, cy] = cp;
        const [x2, y2] = p2;
        let x = (1 - t) * (1 - t) * x1 + 2 * t * (1 - t) * cx + t * t * x2;
        let y = (1 - t) * (1 - t) * y1 + 2 * t * (1 - t) * cy + t * t * y2;
        return [x, y];
    }

2阶贝塞尔曲线
上图为2阶贝塞尔的绘制,是小球从起点p0(180,22)到终点p2(1920,89)的匀速运动,中间受到p1(800,0)坐标影响改变运动轨迹,形成的曲线的运动轨迹

3阶贝塞尔曲线:

在这里插入图片描述

    /**
     * @desc 三阶贝塞尔
     * @param {number} t 当前百分比
     * @param {Array} p1 起点坐标
     * @param {Array} p2 终点坐标
     * @param {Array} cp1 控制点1
     * @param {Array} cp2 控制点2
     */
    threeBezier(t, p1, cp1, cp2, p2) {
        const [x1, y1] = p1;
        const [x2, y2] = p2;
        const [cx1, cy1] = cp1;
        const [cx2, cy2] = cp2;
        let x =
            x1 * (1 - t) * (1 - t) * (1 - t) +
            3 * cx1 * t * (1 - t) * (1 - t) +
            3 * cx2 * t * t * (1 - t) +
            x2 * t * t * t;
        let y =
            y1 * (1 - t) * (1 - t) * (1 - t) +
            3 * cy1 * t * (1 - t) * (1 - t) +
            3 * cy2 * t * t * (1 - t) +
            y2 * t * t * t;
        return [x, y];
    }

3阶贝塞尔曲线
上图为3阶贝塞尔的绘制,是小球从起点p0(0,500)到终点p3(1920,0)的匀速运动,中间受到p1(300,0),p2(1160,500)坐标影响改变运动轨迹,形成的曲线的运动轨迹

4/n阶贝塞尔曲线

在这里插入图片描述

    /**
     * 多阶贝塞尔曲线的生成
     * @param {*} anchorpoints 贝塞尔基点
     * @param {*} pointsAmount 生成的点数
     * @returns 路径点的Array
     */
    CreateBezierPoints(anchorpoints, pointsAmount) {
        let last = anchorpoints[anchorpoints.length-1]
        var points = [];
        for (var i = 0; i < pointsAmount; i++) {
            var point = this.MultiPointBezier(anchorpoints, i / pointsAmount);
            points.push(point);
        }
        return points;
    }

     MultiPointBezier(points, t) {
        var len = points.length;
        var x = 0, y = 0;
        var erxiangshi = function (start, end) {
            var cs = 1, bcs = 1;
            while (end > 0) {
                cs *= start;
                bcs *= end;
                start--;
                end--;
            }
            return (cs / bcs);
        };
        for (var i = 0; i < len; i++) {
            var point = points[i];
            x += point[0] * Math.pow((1 - t), (len - 1 - i)) * Math.pow(t, i) * (erxiangshi(len - 1, i));
            y += point[1] * Math.pow((1 - t), (len - 1 - i)) * Math.pow(t, i) * (erxiangshi(len - 1, i));
        }
        return [x,y];
    }

4阶贝塞尔曲线
上图为4阶贝塞尔的绘制,是小球从起点p0(-17,285)到终点p4(1920,89)的匀速运动,中间受到p1(180,22) p2(1160,1102) p3(1350,-44)坐标影响改变运动轨迹,形成的曲线的运动轨迹

下面为完整的封装和使用:

三 封装和使用

bezier.js

/**
 * @desc 贝塞尔曲线算法,包含了3阶贝塞尔
 */
class Bezier {
    /**
       * @desc 获取点,这里可以设置点的个数
       * @param {number} num 点个数
       * @param {Array} p1 起点坐标
       * @param {Array} p2 终点坐标
       * @param {Array} p3 点坐标
       * @param {Array} p4 点坐标
       * 如果参数是 num, p1, p2 为一阶贝塞尔
       * 如果参数是 num, p1, c1, p2 为二阶贝塞尔
       * 如果参数是 num, p1, c1, c2, p2 为三阶贝塞尔
       */
    getBezierPoints(num = 100, p1, p2, p3, p4) {
        let func;
        const points = [];
        if (!p3 && !p4) {
            func = this.oneBezier;
        } else if (p3 && !p4) {
            func = this.twoBezier;
        } else if (p3 && p4) {
            func = this.threeBezier;
        } else {
            return
        }
        for (let i = 0; i < num; i++) {
            points.push(func(i / num, p1, p2, p3, p4));
        }
        if (p4) {
            points.push([...p4]);
        } else if (p3) {
            points.push([...p3]);
        }
        return points;
    }

    /**
       * @desc 一阶贝塞尔
       * @param {number} t 当前百分比
       * @param {Array} p1 起点坐标
       * @param {Array} p2 终点坐标
       */
    oneBezier(t, p1, p2) {
        const [x1, y1] = p1;
        const [x2, y2] = p2;
        let x = x1 + (x2 - x1) * t;
        let y = y1 + (y2 - y1) * t;
        return [x, y];
    }

    /**
       * @desc 二阶贝塞尔
       * @param {number} t 当前百分比
       * @param {Array} p1 起点坐标
       * @param {Array} p2 终点坐标
       * @param {Array} cp 控制点
       */
    twoBezier(t, p1, cp, p2) {
        const [x1, y1] = p1;
        const [cx, cy] = cp;
        const [x2, y2] = p2;
        let x = (1 - t) * (1 - t) * x1 + 2 * t * (1 - t) * cx + t * t * x2;
        let y = (1 - t) * (1 - t) * y1 + 2 * t * (1 - t) * cy + t * t * y2;
        return [x, y];
    }

    /**
       * @desc 三阶贝塞尔
       * @param {number} t 当前百分比
       * @param {Array} p1 起点坐标
       * @param {Array} p2 终点坐标
       * @param {Array} cp1 控制点1
       * @param {Array} cp2 控制点2
       */
    threeBezier(t, p1, cp1, cp2, p2) {
        const [x1, y1] = p1;
        const [x2, y2] = p2;
        const [cx1, cy1] = cp1;
        const [cx2, cy2] = cp2;
        let x =
            x1 * (1 - t) * (1 - t) * (1 - t) +
            3 * cx1 * t * (1 - t) * (1 - t) +
            3 * cx2 * t * t * (1 - t) +
            x2 * t * t * t;
        let y =
            y1 * (1 - t) * (1 - t) * (1 - t) +
            3 * cy1 * t * (1 - t) * (1 - t) +
            3 * cy2 * t * t * (1 - t) +
            y2 * t * t * t;
        return [x, y];
    }

    /**
       * 多阶贝塞尔曲线的生成
       * @param {*} anchorpoints 贝塞尔基点数组
       * @param {*} pointsAmount 生成的点数
       * @returns 路径点的Array
       */
    CreateBezierPoints(anchorpoints, pointsAmount) {
        // let last = anchorpoints[anchorpoints.length - 1]
        let points = [];
        for (let i = 0; i < pointsAmount; i++) {
            let point = this.MultiPointBezier(anchorpoints, i / pointsAmount);
            points.push(point);
        }
        return points;
    }

    MultiPointBezier(points, t) {
        let len = points.length;
        let x = 0; let y = 0;
        let erxiangshi = function (start, end) {
            let cs = 1; let bcs = 1;
            while (end > 0) {
                cs *= start;
                bcs *= end;
                start--;
                end--;
            }
            return (cs / bcs);
        };
        for (let i = 0; i < len; i++) {
            let point = points[i];
            x += point[0] * Math.pow((1 - t), (len - 1 - i)) * Math.pow(t, i) * (erxiangshi(len - 1, i));
            y += point[1] * Math.pow((1 - t), (len - 1 - i)) * Math.pow(t, i) * (erxiangshi(len - 1, i));
        }
        return [x, y];
    }
}

export default new Bezier();


App.jsx

import './App.scss';
import { useEffect, useState, Fragment } from 'react';
import bezier from './utils/bezier'
import logo from './logo.svg'
import { WOW } from 'wowjs'
import 'animate.css';
// import 'wowjs/css/libs/animate.css';

function App() {

  let [w_width, setWWidth] = useState(window.innerWidth)  //设置幕布宽度
  let [h_height, setHeight] = useState(500)  //设置幕布高度
  let [begin_n, setBeginN] = useState([0, 164])  //开始坐标
  let [end_n, setEndN] = useState([w_width, 40]) //结束坐标
  let [one_n, setOneN] = useState([100, 40]) //bezier坐标1
  let [two_n, setTwoN] = useState([750, 788]) //bezier坐标2
  let [three_n, setThreeN] = useState([800, -30]) //bezier坐标3
  let [one_dot_n, setOneDotN] = useState(40) //生成背景虚线坐标的数量
  let [two_dot_n, setTwoDotN] = useState(10) //生成上层圆的数量
  let [oneXY, setOneXY] = useState() //背景虚线坐标数组
  let [twoXY, setTwoXY] = useState() //上层圆坐标数组
  let [bezier_n, setBezierN] = useState(1) //bezier阶数

  useEffect(() => {

    window.addEventListener('resize', () => {
      // 只要窗口大小发生像素变化就会触发
      setWWidth(window.innerWidth)
    })
    return () => {
      window.removeEventListener('resize', () => { })
    }
  }, [])

  //根据当前屏幕宽度计算各个贝塞尔点坐标
  useEffect(() => {
    console.log('当前屏幕宽', w_width)
    setBeginN([(-17 / 1920) * w_width, (255 / 446) * h_height])
    setEndN([(1920 / 1920) * w_width, (80 / 446) * h_height])
    setOneN([(180 / 1920) * w_width, (20 / 446) * h_height])
    setTwoN([(1160 / 1920) * w_width, (983 / 446) * h_height])
    setThreeN([(1350 / 1920) * w_width, (-40 / 446) * h_height])
  }, [w_width, h_height])

  useEffect(() => {
    new WOW({
      live: false
    }).init()
    console.log('当前坐标组为:', [begin_n, one_n, two_n, three_n, end_n])
    let anchorpoints

    switch (bezier_n) {
      case 1:
        anchorpoints = [begin_n, end_n]
        break;
      case 2:
        anchorpoints = [begin_n, one_n, end_n]
        break;
      case 3:
        anchorpoints = [begin_n, one_n, two_n, end_n]
        break;
      default:
        anchorpoints = [begin_n, one_n, two_n, three_n, end_n]
        break;
    }

    let oneXY = bezier.CreateBezierPoints(
      anchorpoints,
      one_dot_n
    )

    //计算背景虚线的斜率
    oneXY.forEach((value, key) => {
      if (oneXY[key + 1]) {
        let nextX = oneXY[key + 1][0]
        let nextY = oneXY[key + 1][1]
        let thisX = value[0]
        let thisY = value[1]
        let xl = (((nextY - thisY) / (nextX - thisX)) * 100) / 2
        oneXY[key] = [...value, xl]
        // console.log(`第${key}个坐标斜率为:${xl}`)
        // console.log(value)
      }
    })
    // console.log(oneXY)
    setOneXY(oneXY)

    let twoXY = bezier.CreateBezierPoints(
      anchorpoints,
      two_dot_n
    )
    setTwoXY(twoXY)
  }, [begin_n, one_n, two_n, three_n, end_n, one_dot_n, two_dot_n, bezier_n])

  let arrayChange = (array, number, element) => {
    let newValue = [...array]
    newValue[number] = parseFloat(element.target.value)
    console.log(newValue)
    return newValue
  }


  return (
    <div className="App">
      <div className="inputNum">
        <h2>
          贝塞尔曲线参数:<br />
          幕布宽 <input type="number" value={w_width} onChange={(el) => { setWWidth(el.target.value) }} /><br />
          幕布高度 <input type="number" value={h_height} onChange={(el) => { setHeight(el.target.value) }} /><br />
          Bezier阶数 <input type="number" value={bezier_n} onChange={(el) => { setBezierN(parseInt(el.target.value)) }} />
        </h2>
        <div className="left">
          <div className="param_group">
            起点:
            <input type="number" placeholder="X轴" value={begin_n[0]} onChange={(el) => { setBeginN(arrayChange(begin_n, 0, el)) }} />
            <input type="number" placeholder="Y轴" value={begin_n[1]} onChange={(el) => { setBeginN(arrayChange(begin_n, 1, el)) }} />
          </div>
          <div className="param_group">
            1点:
            <input type="number" placeholder="X轴" value={one_n[0]} onChange={(el) => { setOneN(arrayChange(one_n, 0, el)) }} />
            <input type="number" placeholder="Y轴" value={one_n[1]} onChange={(el) => { setOneN(arrayChange(one_n, 1, el)) }} />
          </div>
          <div className="param_group">
            2点:
            <input type="number" placeholder="X轴" value={two_n[0]} onChange={(el) => { setTwoN(arrayChange(two_n, 0, el)) }} />
            <input type="number" placeholder="Y轴" value={two_n[1]} onChange={(el) => { setTwoN(arrayChange(two_n, 1, el)) }} />
          </div>
          <div className="param_group">
            3点:
            <input type="number" placeholder="X轴" value={three_n[0]} onChange={(el) => { setThreeN(arrayChange(three_n, 0, el)) }} />
            <input type="number" placeholder="Y轴" value={three_n[1]} onChange={(el) => { setThreeN(arrayChange(three_n, 1, el)) }} />
          </div>
          <div className="param_group">
            终点:
            <input type="number" placeholder="X轴" value={end_n[0]} onChange={(el) => { setEndN(arrayChange(end_n, 0, el)) }} />
            <input type="number" placeholder="Y轴" value={end_n[1]} onChange={(el) => { setEndN(arrayChange(end_n, 1, el)) }} />
          </div>
        </div>
        <div className="right">
          <div className="param_group">
            曲线数量:
            <input type="text" value={one_dot_n} onChange={(el) => { setOneDotN(el.target.value) }} />
          </div>
          <div className="param_group">
            元素数量:
            <input type="text" value={two_dot_n} onChange={(el) => { setTwoDotN(el.target.value) }} />
          </div>
        </div>
      </div>
      <div className="main-container" style={{
        width: `${w_width}px`,
        height: `${h_height}px`
      }}>
        <Fragment>
          {
            oneXY ? oneXY.map((v, k) => {
              return (
                <span
                  key={`${k}one`}
                  className={`dot${k} wow`}
                  data-wow-delay={`${k * 60}ms`}
                  data-wow-duration="1s"
                  style={{
                    left: `${v[0]}px`,
                    top: `${v[1]}px`,
                    transform: `rotate(${v[2]}deg) translate(-50%, -50%)`,
                  }}>
                </span>
              )
            }) : ''
          }
        </Fragment>

        <Fragment>
          {
            twoXY ? twoXY.map((v, k) => {
              return (
                <div
                  className={`domain-infos${k} wow`}
                  key={`${k}two`}
                  data-wow-delay={`${k * 300 + 2000}ms`}
                  data-wow-duration="4s"
                  style={{
                    left: `${v[0]}px`,
                    top: `${v[1]}px`,
                    display: k > 0 ? '' : 'none',
                    'flexDirection': k % 2 === 0 ? 'column-reverse' : 'column',
                  }}
                >
                  <div
                    className="domain-img_o"
                    data-wow-delay="2s"
                    data-wow-duration="2s">
                    <img className="domain-img_item" src={logo} alt="" />
                  </div>
                  <div className="domain-name">[{parseInt(v[0])},{parseInt(v[1])}]</div>
                </div>
              )
            }) : ''
          }
        </Fragment>
      </div>
    </div>
  );
}

export default App;


App.scss


@keyframes dotchange {
  0% {
    opacity: 0;
    visibility: hidden;
  }

  20% {
    opacity: .2;
    visibility: visible;
  }

  40% {
    opacity: .4;
    visibility: visible;
  }

  60% {
    opacity: .6;
    visibility: visible;
  }

  80% {
    opacity: .8;
    visibility: visible;
  }

  100% {
    opacity: 1;
    visibility: visible;
  }
}

@keyframes mymove {
  0% {
    top: 0px;
  }

  30% {
    top: -10px;
  }

  60% {
    top: -20px;
  }

  100% {
    top: -32px;
  }
}

.App {
  width: 100%;
  background: pink;
  height: 100vh;
  color: #000000;
}

h2 {
  font-size: 15px;
  line-height: 15px;
  // color: #ffffff;
  text-align: center;
}

.inputNum {
  width: 60%;
  padding-top: 50px;
  margin: 50px auto;
  display: flex;
  align-items: center;

  .right {
    margin-left: 40px;
  }

  .param_group {
    margin-top: 5px;
    display: flex;
    justify-content: center;
    align-items: center;

    input {
      width: 60px;
      z-index: 12;
    }
  }
}

.main-container {
  margin: 10px auto;
  width: 100%;
  height: 500px;
  background: #00022f;
  position: relative;
  overflow-x: clip;
}

[class^=dot] {
  position: absolute;
  width: 6px;
  height: 3px;
  border-radius: 4px;
  display: inline-block;
  background: #34ccff;
  font-size: 12px;
  color: #ccc;
  visibility: hidden;
  opacity: 0;
  animation: dotchange linear;
  animation-fill-mode: both;
}


[class^=domain-infos] {
  position: absolute;
  display: flex;
  align-items: center;
  flex-direction: column;
  width: 60px;
  height: 60px;
  visibility: hidden;
  opacity: 0;
  animation: dotchange linear;
  animation-fill-mode: both;
  transform: translate(-50%, -50%);

  &:hover {
    .domain-img_o {
      visibility: visible !important;
      opacity: 1 !important;

      .domain-img_item {
        visibility: visible !important;
      }
    }
  }

  &:hover {

    .domain-name {
      opacity: 1;
    }
  }

  .domain-img_o {
    border-radius: 50%;
    background: rgba(52, 204, 255, 0.2);
    animation: dotchange linear;
    animation-fill-mode: both;
    display: flex;
    align-items: center;
    justify-content: center;


    .domain-img_item {
      width: 60px;
      height: 60px;
      border-radius: 50%;
    }
  }

  .domain-name {
    padding: 20px 0;
    font-family: 'DINNextLTPro-Regular';
    font-weight: 700;
    font-size: 16px;
    line-height: 19px;
    color: #ffffff;
    opacity: 0.5;
    text-align: center;
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/11949.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【7-创建商城系统的子模块并将修改后的信息使用Git提交到Gitee上】

一.知识回顾 【0.三高商城系统的专题专栏都帮你整理好了&#xff0c;请点击这里&#xff01;】 【1-系统架构演进过程】 【2-微服务系统架构需求】 【3-高性能、高并发、高可用的三高商城系统项目介绍】 【4-Linux云服务器上安装Docker】 【5-Docker安装部署MySQL和Redis服务】…

测试.net开源敏感词检测库ToolGood.Words

微信公众号“DotNet”看到介绍.net开源敏感词检测库ToolGood.Words的文章《.NET Core一款高性能敏感词检测开源库》&#xff0c;根据参考文献2中的测试&#xff0c;该库的检测效率比C#自带的正则效率高8.8倍&#xff0c;如果数量量越大性能优势越明显。   ToolGood.Words的Gi…

英文Paper写作如何尽量避免抄袭?

说到英文Paper的写作&#xff0c;我们就不得不提到reference&#xff0c;中文称之为引用。在国外&#xff0c;合理正确的利用reference非常重要&#xff0c;国外对于知识产权的保护很严格&#xff0c;对于抄袭行为也是不能容忍的。学术表现差或是学术不诚实问题是造成学生被开除…

4.构造类型,类型转换

构造类型 由若干各个相同或不同类型的数据构成的集合&#xff0c;这种集合类型被称为构造类型 例&#xff1a;int a[10]; 数组、结构体、共用体、枚举 类型转换 数据有不同的类型&#xff0c;不同类型数据之间进行混合运算时必然涉及到类型转换的问题。 转换的方式有两种&am…

使用verdaccio搭建私有组件库

前言 最近公司需要根据现有的公用组件搭建一套私有组件库&#xff0c;方便其他项目使用&#xff0c;然后经过一系列尝试和走了许多坑&#xff0c;终于搭建成功了&#xff0c;这里记录下搭建步骤&#xff0c;希望对你有些帮助。 为什么选择verdaccio 由于公司组件库越来越多&…

ZZNUOJ_Java软件的下载安装和写代码

ZZNUOJ_Java软件的下载安装和写代码一、Java软件myeclipse图标二、下载安装的步骤三、使用myeclipse软件1、创建项目名和类名的步骤2、写代码和运行结果一、Java软件 myeclipse图标 二、下载安装的步骤 第一步骤&#xff1a;下载myeclipse&#xff1a;myeclipse 第二步骤&…

怎么把旧电脑的用户配置文件迁移到新电脑

您购买了一台新笔记本电脑&#xff0c;但不想花大量时间重新下载、编辑、备份旧电脑上的所有文件&#xff0c;也不想重新安装常用的软件&#xff0c;更不想重新配置电脑账户&#xff0c;那么&#xff0c;应该怎么把旧电脑的用户配置文件迁移到新电脑&#xff1f; 一、如何迁移用…

[附源码]java毕业设计基于疫情防控物流管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

BDP 581/591 azide,Bodipy581/591标记叠氮,2183473-20-1

产品名称&#xff1a;Bodipy581/591标记叠氮 英文名称&#xff1a;BDP 581/591 azide CAS&#xff1a;2183473-20-1 BDP 581/591是一种相对疏水的明亮且多用途的荧光团。 结构式&#xff1a; General properties Appearance: dark solid Molecular weight: 474.31 分子式…

中台深入剖析和实现技巧

什么是中台 中台发展史 无共享架构-大烟囱架构 共享架构模式 IaaS架构 PaaS架构 SaaS架构 中台架构 中台定义 中台就是“企业级的能力复用平台”-Thoughtworks 首席咨询师王健 中台是将系统的通用化能力进行打包整合&#xff0c;通过接口的形式赋能到外部系统&#xff0c;从…

jsp教育培训系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 教育培训系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql&#xff0c;使用jav…

[附源码]java毕业设计教务系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

计算机网络:IEEE 802.11无线局域网

文章目录1.无线局域网的组成(1)有固定基础设施无线局域网(2)无固定基础设施移动自组织网络2.802.11局域网的MAC帧1.无线局域网的组成 无线局域网可分为两大类:有固定基础设施的无线局域网和无固定基础设施的移动自组织网络。所谓“固定基础设施”&#xff0c;是指预先建立的、…

[附源码]java毕业设计基于智能推荐的房屋租赁系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Docker(狂神)

Docker概述 Docker为什么出现&#xff1f; 一款产品&#xff1a;开发&#xff0c;上线&#xff0c;两套环境&#xff0c;应用环境&#xff0c;应用配置 开发&#xff0c;运维 环境配置十分麻烦&#xff0c;每一个机器都要部署环境&#xff0c;费时费力。 发布一个项目&#xff…

数据流与重定向,vim练习,grep过滤练习,cut练习

今日作业&#xff1a; 1、重定向练习&#xff1a;将根目录下的文件的文件名写入/test/file文件中&#xff08;先切换到根目录&#xff0c;再查看根目录下的文件名&#xff0c;进行数据重定向&#xff0c;最后查看/test/file文件&#xff09; 2、vim命令练习&#xff1a;将/root…

景区讲解小程序,扫码轻松获取多语言讲解服务

中国旅游研究院连续40个季度监测&#xff0c;提取了游客对景区的五大负面评价关键词。 分别是&#xff1a; 1、空间拥堵 2、体验感下降 3、人性化服务不足 4、纪念品和旅游购物同质化 5、娱乐项目不够丰富 这些评价词也为景区的升级转型、服务提升指明了方向。 其中“体验感下…

RESTful+统一响应体+API自动文档的SprinBoot项目

一、项目要求 实验环境&#xff1a;IdeamysqlJDKTomcatMaven将上一周个人作业用 RESTful 接口实现&#xff1b;&#xff08;上周的SpringBootMybatisCRUD项目&#xff09;配置统一响应体&#xff1b;配置Swagger&#xff0c;生成API自动文档&#xff1b;对 RESTful 接口用Post…

同态加密开源框架整理

开放隐私计算 2022-11-16 19:17 发表于浙江 以下文章来源于隐私计算研习社 &#xff0c;作者庄智廉 隐私计算研习社. 开放隐私计算社区 开放隐私计算 开放隐私计算OpenMPC是国内第一个且影响力最大的隐私计算开放社区。社区秉承开放共享的精神&#xff0c;专注于隐私计算行业…

2022年数维杯国际赛D题 极端天气损失评估与应对策略

2022年7月至8月&#xff0c;中国南方许多城市经历了多日的炎热天气&#xff0c;而北方部分地区也出现了大 规模的强降水。此外&#xff0c;许多欧洲国家也经历了历史上罕见的干旱灾害。无论是南部的高温天气 &#xff0c;北方的强降水&#xff0c;还是欧洲的干旱天气&#x…