前端及开发文章及欣赏

好看的圣诞树(动态效果) 转自 csdn

前端达人

、制作方法 

1.复制代码到Dreamweaver或HBuilder或vscode中

2.点击运行---运行到浏览器---选择你要打开的浏览器

3.打开后会出现这个界面,前四个是固定音乐,最后一个是自主选择的音乐,你可以选择你电脑上的歌曲,什么歌曲都行(第一次打开可能会有点慢,稍等片刻即可,选择音乐的时候点一下没反应的话多点几下即可,第一次打开这属于正常现象)

 

4.特别提醒:打开的时候电脑一定要处于联网状态
 

三、源代码

 
  1.  
    <!DOCTYPE html>
  2.  
    <html lang="en">
  3.  
     
  4.  
    <head>
  5.  
    <meta charset="UTF-8">
  6.  
     
  7.  
    <title>圣诞树</title>
  8.  
     
  9.  
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
  10.  
     
  11.  
    <style>
  12.  
    * {
  13.  
    box-sizing: border-box;
  14.  
    }
  15.  
     
  16.  
     
  17.  
    body {
  18.  
    margin: 0;
  19.  
    height: 100vh;
  20.  
    overflow: hidden;
  21.  
    display: flex;
  22.  
    align-items: center;
  23.  
    justify-content: center;
  24.  
    background: #161616;
  25.  
    color: #c5a880;
  26.  
    font-family: sans-serif;
  27.  
    }
  28.  
     
  29.  
     
  30.  
    label {
  31.  
    display: inline-block;
  32.  
    background-color: #161616;
  33.  
    padding: 16px;
  34.  
    border-radius: 0.3rem;
  35.  
    cursor: pointer;
  36.  
    margin-top: 1rem;
  37.  
    width: 300px;
  38.  
    border-radius: 10px;
  39.  
    border: 1px solid #c5a880;
  40.  
    text-align: center;
  41.  
    }
  42.  
     
  43.  
     
  44.  
    ul {
  45.  
    list-style-type: none;
  46.  
    padding: 0;
  47.  
    margin: 0;
  48.  
    }
  49.  
     
  50.  
     
  51.  
    .btn {
  52.  
    background-color: #161616;
  53.  
    border-radius: 10px;
  54.  
    color: #c5a880;
  55.  
    border: 1px solid #c5a880;
  56.  
    padding: 16px;
  57.  
    width: 300px;
  58.  
    margin-bottom: 16px;
  59.  
    line-height: 1.5;
  60.  
    cursor: pointer;
  61.  
    }
  62.  
     
  63.  
    .separator {
  64.  
    font-weight: bold;
  65.  
    text-align: center;
  66.  
    width: 300px;
  67.  
    margin: 16px 0px;
  68.  
    color: #a07676;
  69.  
    }
  70.  
     
  71.  
     
  72.  
    .title {
  73.  
    color: #a07676;
  74.  
    font-weight: bold;
  75.  
    font-size: 1.25rem;
  76.  
    margin-bottom: 16px;
  77.  
    }
  78.  
     
  79.  
     
  80.  
    .text-loading {
  81.  
    font-size: 2rem;
  82.  
    }
  83.  
    </style>
  84.  
     
  85.  
    <script>
  86.  
    window.console = window.console || function (t) { };
  87.  
    </script>
  88.  
     
  89.  
     
  90.  
     
  91.  
    <script>
  92.  
    if (document.location.search.match(/type=embed/gi)) {
  93.  
    window.parent.postMessage("resize", "*");
  94.  
    }
  95.  
    </script>
  96.  
     
  97.  
     
  98.  
    </head>
  99.  
     
  100.  
    <body translate="no">
  101.  
    <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/build/three.min.js"></script>
  102.  
    <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/postprocessing/EffectComposer.js"></script>
  103.  
    <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/postprocessing/RenderPass.js"></script>
  104.  
    <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/postprocessing/ShaderPass.js"></script>
  105.  
    <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/shaders/CopyShader.js"></script>
  106.  
    <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/shaders/LuminosityHighPassShader.js"></script>
  107.  
    <script src="https://cdn.jsdelivr.net/npm/three@0.115.0/examples/js/postprocessing/UnrealBloomPass.js"></script>
  108.  
     
  109.  
    <div id="overlay">
  110.  
    <ul>
  111.  
    <li class="title">请选择音乐</li>
  112.  
    <li>
  113.  
    <button class="btn" id="btnA" type="button">
  114.  
    Snowflakes Falling Down by Simon Panrucker
  115.  
    </button>
  116.  
    </li>
  117.  
    <li><button class="btn" id="btnB" type="button">This Christmas by Dott</button></li>
  118.  
    <li><button class="btn" id="btnC" type="button">No room at the inn by TRG Banks</button></li>
  119.  
    <li><button class="btn" id="btnD" type="button">Jingle Bell Swing by Mark Smeby</button></li>
  120.  
    <li class="separator">或者</li>
  121.  
    <li>
  122.  
    <input type="file" id="upload" hidden />
  123.  
    <label for="upload">Upload File</label>
  124.  
    </li>
  125.  
    </ul>
  126.  
    </div>
  127.  
     
  128.  
    <script id="rendered-js">
  129.  
    const { PI, sin, cos } = Math;
  130.  
    const TAU = 2 * PI;
  131.  
     
  132.  
    const map = (value, sMin, sMax, dMin, dMax) => {
  133.  
    return dMin + (value - sMin) / (sMax - sMin) * (dMax - dMin);
  134.  
    };
  135.  
     
  136.  
    const range = (n, m = 0) =>
  137.  
    Array(n).
  138.  
    fill(m).
  139.  
    map((i, j) => i + j);
  140.  
     
  141.  
    const rand = (max, min = 0) => min + Math.random() * (max - min);
  142.  
    const randInt = (max, min = 0) => Math.floor(min + Math.random() * (max - min));
  143.  
    const randChoise = arr => arr[randInt(arr.length)];
  144.  
    const polar = (ang, r = 1) => [r * cos(ang), r * sin(ang)];
  145.  
     
  146.  
    let scene, camera, renderer, analyser;
  147.  
    let step = 0;
  148.  
    const uniforms = {
  149.  
    time: { type: "f", value: 0.0 },
  150.  
    step: { type: "f", value: 0.0 }
  151.  
    };
  152.  
     
  153.  
    const params = {
  154.  
    exposure: 1,
  155.  
    bloomStrength: 0.9,
  156.  
    bloomThreshold: 0,
  157.  
    bloomRadius: 0.5
  158.  
    };
  159.  
     
  160.  
    let composer;
  161.  
     
  162.  
    const fftSize = 2048;
  163.  
    const totalPoints = 4000;
  164.  
     
  165.  
    const listener = new THREE.AudioListener();
  166.  
     
  167.  
    const audio = new THREE.Audio(listener);
  168.  
     
  169.  
    document.querySelector("input").addEventListener("change", uploadAudio, false);
  170.  
     
  171.  
    const buttons = document.querySelectorAll(".btn");
  172.  
    buttons.forEach((button, index) =>
  173.  
    button.addEventListener("click", () => loadAudio(index)));
  174.  
     
  175.  
     
  176.  
    function init() {
  177.  
    const overlay = document.getElementById("overlay");
  178.  
    overlay.remove();
  179.  
     
  180.  
    scene = new THREE.Scene();
  181.  
    renderer = new THREE.WebGLRenderer({ antialias: true });
  182.  
    renderer.setPixelRatio(window.devicePixelRatio);
  183.  
    renderer.setSize(window.innerWidth, window.innerHeight);
  184.  
    document.body.appendChild(renderer.domElement);
  185.  
     
  186.  
    camera = new THREE.PerspectiveCamera(
  187.  
    60,
  188.  
    window.innerWidth / window.innerHeight,
  189.  
    1,
  190.  
    1000);
  191.  
     
  192.  
    camera.position.set(-0.09397456774197047, -2.5597086635726947, 24.420789670889008);
  193.  
    camera.rotation.set(0.10443543723052419, -0.003827152981119352, 0.0004011488708739715);
  194.  
     
  195.  
    const format = renderer.capabilities.isWebGL2 ?
  196.  
    THREE.RedFormat :
  197.  
    THREE.LuminanceFormat;
  198.  
     
  199.  
    uniforms.tAudioData = {
  200.  
    value: new THREE.DataTexture(analyser.data, fftSize / 2, 1, format)
  201.  
    };
  202.  
     
  203.  
     
  204.  
    addPlane(scene, uniforms, 3000);
  205.  
    addSnow(scene, uniforms);
  206.  
     
  207.  
    range(10).map(i => {
  208.  
    addTree(scene, uniforms, totalPoints, [20, 0, -20 * i]);
  209.  
    addTree(scene, uniforms, totalPoints, [-20, 0, -20 * i]);
  210.  
    });
  211.  
     
  212.  
    const renderScene = new THREE.RenderPass(scene, camera);
  213.  
     
  214.  
    const bloomPass = new THREE.UnrealBloomPass(
  215.  
    new THREE.Vector2(window.innerWidth, window.innerHeight),
  216.  
    1.5,
  217.  
    0.4,
  218.  
    0.85);
  219.  
     
  220.  
    bloomPass.threshold = params.bloomThreshold;
  221.  
    bloomPass.strength = params.bloomStrength;
  222.  
    bloomPass.radius = params.bloomRadius;
  223.  
     
  224.  
    composer = new THREE.EffectComposer(renderer);
  225.  
    composer.addPass(renderScene);
  226.  
    composer.addPass(bloomPass);
  227.  
     
  228.  
    addListners(camera, renderer, composer);
  229.  
    animate();
  230.  
    }
  231.  
     
  232.  
    function animate(time) {
  233.  
    analyser.getFrequencyData();
  234.  
    uniforms.tAudioData.value.needsUpdate = true;
  235.  
    step = (step + 1) % 1000;
  236.  
    uniforms.time.value = time;
  237.  
    uniforms.step.value = step;
  238.  
    composer.render();
  239.  
    requestAnimationFrame(animate);
  240.  
    }
  241.  
     
  242.  
    function loadAudio(i) {
  243.  
    document.getElementById("overlay").innerHTML =
  244.  
    '<div class="text-loading">正在下载音乐,请稍等...</div>';
  245.  
    const files = [
  246.  
    "https://files.freemusicarchive.org/storage-freemusicarchive-org/music/no_curator/Simon_Panrucker/Happy_Christmas_You_Guys/Simon_Panrucker_-_01_-_Snowflakes_Falling_Down.mp3",
  247.  
    "https://files.freemusicarchive.org/storage-freemusicarchive-org/music/no_curator/Dott/This_Christmas/Dott_-_01_-_This_Christmas.mp3",
  248.  
    "https://files.freemusicarchive.org/storage-freemusicarchive-org/music/ccCommunity/TRG_Banks/TRG_Banks_Christmas_Album/TRG_Banks_-_12_-_No_room_at_the_inn.mp3",
  249.  
    "https://files.freemusicarchive.org/storage-freemusicarchive-org/music/ccCommunity/Mark_Smeby/En_attendant_Nol/Mark_Smeby_-_07_-_Jingle_Bell_Swing.mp3"];
  250.  
     
  251.  
    const file = files[i];
  252.  
     
  253.  
    const loader = new THREE.AudioLoader();
  254.  
    loader.load(file, function (buffer) {
  255.  
    audio.setBuffer(buffer);
  256.  
    audio.play();
  257.  
    analyser = new THREE.AudioAnalyser(audio, fftSize);
  258.  
    init();
  259.  
    });
  260.  
     
  261.  
     
  262.  
     
  263.  
     
  264.  
    }
  265.  
     
  266.  
     
  267.  
    function uploadAudio(event) {
  268.  
    document.getElementById("overlay").innerHTML =
  269.  
    '<div class="text-loading">请稍等...</div>';
  270.  
    const files = event.target.files;
  271.  
    const reader = new FileReader();
  272.  
     
  273.  
    reader.onload = function (file) {
  274.  
    var arrayBuffer = file.target.result;
  275.  
     
  276.  
    listener.context.decodeAudioData(arrayBuffer, function (audioBuffer) {
  277.  
    audio.setBuffer(audioBuffer);
  278.  
    audio.play();
  279.  
    analyser = new THREE.AudioAnalyser(audio, fftSize);
  280.  
    init();
  281.  
    });
  282.  
    };
  283.  
     
  284.  
    reader.readAsArrayBuffer(files[0]);
  285.  
    }
  286.  
     
  287.  
    function addTree(scene, uniforms, totalPoints, treePosition) {
  288.  
    const vertexShader = `
  289.  
    attribute float mIndex;
  290.  
    varying vec3 vColor;
  291.  
    varying float opacity;
  292.  
    uniform sampler2D tAudioData;
  293.  
    float norm(float value, float min, float max ){
  294.  
    return (value - min) / (max - min);
  295.  
    }
  296.  
    float lerp(float norm, float min, float max){
  297.  
    return (max - min) * norm + min;
  298.  
    }
  299.  
    float map(float value, float sourceMin, float sourceMax, float destMin, float destMax){
  300.  
    return lerp(norm(value, sourceMin, sourceMax), destMin, destMax);
  301.  
    }
  302.  
    void main() {
  303.  
    vColor = color;
  304.  
    vec3 p = position;
  305.  
    vec4 mvPosition = modelViewMatrix * vec4( p, 1.0 );
  306.  
    float amplitude = texture2D( tAudioData, vec2( mIndex, 0.1 ) ).r;
  307.  
    float amplitudeClamped = clamp(amplitude-0.4,0.0, 0.6 );
  308.  
    float sizeMapped = map(amplitudeClamped, 0.0, 0.6, 1.0, 20.0);
  309.  
    opacity = map(mvPosition.z , -200.0, 15.0, 0.0, 1.0);
  310.  
    gl_PointSize = sizeMapped * ( 100.0 / -mvPosition.z );
  311.  
    gl_Position = projectionMatrix * mvPosition;
  312.  
    }
  313.  
    `;
  314.  
    const fragmentShader = `
  315.  
    varying vec3 vColor;
  316.  
    varying float opacity;
  317.  
    uniform sampler2D pointTexture;
  318.  
    void main() {
  319.  
    gl_FragColor = vec4( vColor, opacity );
  320.  
    gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord );
  321.  
    }
  322.  
    `;
  323.  
    const shaderMaterial = new THREE.ShaderMaterial({
  324.  
    uniforms: {
  325.  
    ...uniforms,
  326.  
    pointTexture: {
  327.  
    value: new THREE.TextureLoader().load(`https://assets.codepen.io/3685267/spark1.png`)
  328.  
    }
  329.  
    },
  330.  
     
  331.  
     
  332.  
    vertexShader,
  333.  
    fragmentShader,
  334.  
    blending: THREE.AdditiveBlending,
  335.  
    depthTest: false,
  336.  
    transparent: true,
  337.  
    vertexColors: true
  338.  
    });
  339.  
     
  340.  
     
  341.  
    const geometry = new THREE.BufferGeometry();
  342.  
    const positions = [];
  343.  
    const colors = [];
  344.  
    const sizes = [];
  345.  
    const phases = [];
  346.  
    const mIndexs = [];
  347.  
     
  348.  
    const color = new THREE.Color();
  349.  
     
  350.  
    for (let i = 0; i < totalPoints; i++) {
  351.  
    const t = Math.random();
  352.  
    const y = map(t, 0, 1, -8, 10);
  353.  
    const ang = map(t, 0, 1, 0, 6 * TAU) + TAU / 2 * (i % 2);
  354.  
    const [z, x] = polar(ang, map(t, 0, 1, 5, 0));
  355.  
     
  356.  
    const modifier = map(t, 0, 1, 1, 0);
  357.  
    positions.push(x + rand(-0.3 * modifier, 0.3 * modifier));
  358.  
    positions.push(y + rand(-0.3 * modifier, 0.3 * modifier));
  359.  
    positions.push(z + rand(-0.3 * modifier, 0.3 * modifier));
  360.  
     
  361.  
    color.setHSL(map(i, 0, totalPoints, 1.0, 0.0), 1.0, 0.5);
  362.  
     
  363.  
    colors.push(color.r, color.g, color.b);
  364.  
    phases.push(rand(1000));
  365.  
    sizes.push(1);
  366.  
    const mIndex = map(i, 0, totalPoints, 1.0, 0.0);
  367.  
    mIndexs.push(mIndex);
  368.  
    }
  369.  
     
  370.  
    geometry.setAttribute(
  371.  
    "position",
  372.  
    new THREE.Float32BufferAttribute(positions, 3).setUsage(
  373.  
    THREE.DynamicDrawUsage));
  374.  
     
  375.  
     
  376.  
    geometry.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3));
  377.  
    geometry.setAttribute("size", new THREE.Float32BufferAttribute(sizes, 1));
  378.  
    geometry.setAttribute("phase", new THREE.Float32BufferAttribute(phases, 1));
  379.  
    geometry.setAttribute("mIndex", new THREE.Float32BufferAttribute(mIndexs, 1));
  380.  
     
  381.  
    const tree = new THREE.Points(geometry, shaderMaterial);
  382.  
     
  383.  
    const [px, py, pz] = treePosition;
  384.  
     
  385.  
    tree.position.x = px;
  386.  
    tree.position.y = py;
  387.  
    tree.position.z = pz;
  388.  
     
  389.  
    scene.add(tree);
  390.  
    }
  391.  
     
  392.  
    function addSnow(scene, uniforms) {
  393.  
    const vertexShader = `
  394.  
    attribute float size;
  395.  
    attribute float phase;
  396.  
    attribute float phaseSecondary;
  397.  
    varying vec3 vColor;
  398.  
    varying float opacity;
  399.  
    uniform float time;
  400.  
    uniform float step;
  401.  
    float norm(float value, float min, float max ){
  402.  
    return (value - min) / (max - min);
  403.  
    }
  404.  
    float lerp(float norm, float min, float max){
  405.  
    return (max - min) * norm + min;
  406.  
    }
  407.  
    float map(float value, float sourceMin, float sourceMax, float destMin, float destMax){
  408.  
    return lerp(norm(value, sourceMin, sourceMax), destMin, destMax);
  409.  
    }
  410.  
    void main() {
  411.  
    float t = time* 0.0006;
  412.  
    vColor = color;
  413.  
    vec3 p = position;
  414.  
    p.y = map(mod(phase+step, 1000.0), 0.0, 1000.0, 25.0, -8.0);
  415.  
    p.x += sin(t+phase);
  416.  
    p.z += sin(t+phaseSecondary);
  417.  
    opacity = map(p.z, -150.0, 15.0, 0.0, 1.0);
  418.  
    vec4 mvPosition = modelViewMatrix * vec4( p, 1.0 );
  419.  
    gl_PointSize = size * ( 100.0 / -mvPosition.z );
  420.  
    gl_Position = projectionMatrix * mvPosition;
  421.  
    }
  422.  
    `;
  423.  
     
  424.  
    const fragmentShader = `
  425.  
    uniform sampler2D pointTexture;
  426.  
    varying vec3 vColor;
  427.  
    varying float opacity;
  428.  
    void main() {
  429.  
    gl_FragColor = vec4( vColor, opacity );
  430.  
    gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord );
  431.  
    }
  432.  
    `;
  433.  
    function createSnowSet(sprite) {
  434.  
    const totalPoints = 300;
  435.  
    const shaderMaterial = new THREE.ShaderMaterial({
  436.  
    uniforms: {
  437.  
    ...uniforms,
  438.  
    pointTexture: {
  439.  
    value: new THREE.TextureLoader().load(sprite)
  440.  
    }
  441.  
    },
  442.  
     
  443.  
     
  444.  
    vertexShader,
  445.  
    fragmentShader,
  446.  
    blending: THREE.AdditiveBlending,
  447.  
    depthTest: false,
  448.  
    transparent: true,
  449.  
    vertexColors: true
  450.  
    });
  451.  
     
  452.  
     
  453.  
    const geometry = new THREE.BufferGeometry();
  454.  
    const positions = [];
  455.  
    const colors = [];
  456.  
    const sizes = [];
  457.  
    const phases = [];
  458.  
    const phaseSecondaries = [];
  459.  
     
  460.  
    const color = new THREE.Color();
  461.  
     
  462.  
    for (let i = 0; i < totalPoints; i++) {
  463.  
    const [x, y, z] = [rand(25, -25), 0, rand(15, -150)];
  464.  
    positions.push(x);
  465.  
    positions.push(y);
  466.  
    positions.push(z);
  467.  
     
  468.  
    color.set(randChoise(["#f1d4d4", "#f1f6f9", "#eeeeee", "#f1f1e8"]));
  469.  
     
  470.  
    colors.push(color.r, color.g, color.b);
  471.  
    phases.push(rand(1000));
  472.  
    phaseSecondaries.push(rand(1000));
  473.  
    sizes.push(rand(4, 2));
  474.  
    }
  475.  
     
  476.  
    geometry.setAttribute(
  477.  
    "position",
  478.  
    new THREE.Float32BufferAttribute(positions, 3));
  479.  
     
  480.  
    geometry.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3));
  481.  
    geometry.setAttribute("size", new THREE.Float32BufferAttribute(sizes, 1));
  482.  
    geometry.setAttribute("phase", new THREE.Float32BufferAttribute(phases, 1));
  483.  
    geometry.setAttribute(
  484.  
    "phaseSecondary",
  485.  
    new THREE.Float32BufferAttribute(phaseSecondaries, 1));
  486.  
     
  487.  
     
  488.  
    const mesh = new THREE.Points(geometry, shaderMaterial);
  489.  
     
  490.  
    scene.add(mesh);
  491.  
    }
  492.  
    const sprites = [
  493.  
    "https://assets.codepen.io/3685267/snowflake1.png",
  494.  
    "https://assets.codepen.io/3685267/snowflake2.png",
  495.  
    "https://assets.codepen.io/3685267/snowflake3.png",
  496.  
    "https://assets.codepen.io/3685267/snowflake4.png",
  497.  
    "https://assets.codepen.io/3685267/snowflake5.png"];
  498.  
     
  499.  
    sprites.forEach(sprite => {
  500.  
    createSnowSet(sprite);
  501.  
    });
  502.  
    }
  503.  
     
  504.  
    function addPlane(scene, uniforms, totalPoints) {
  505.  
    const vertexShader = `
  506.  
    attribute float size;
  507.  
    attribute vec3 customColor;
  508.  
    varying vec3 vColor;
  509.  
    void main() {
  510.  
    vColor = customColor;
  511.  
    vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
  512.  
    gl_PointSize = size * ( 300.0 / -mvPosition.z );
  513.  
    gl_Position = projectionMatrix * mvPosition;
  514.  
    }
  515.  
    `;
  516.  
    const fragmentShader = `
  517.  
    uniform vec3 color;
  518.  
    uniform sampler2D pointTexture;
  519.  
    varying vec3 vColor;
  520.  
    void main() {
  521.  
    gl_FragColor = vec4( vColor, 1.0 );
  522.  
    gl_FragColor = gl_FragColor * texture2D( pointTexture, gl_PointCoord );
  523.  
    }
  524.  
    `;
  525.  
    const shaderMaterial = new THREE.ShaderMaterial({
  526.  
    uniforms: {
  527.  
    ...uniforms,
  528.  
    pointTexture: {
  529.  
    value: new THREE.TextureLoader().load(`https://assets.codepen.io/3685267/spark1.png`)
  530.  
    }
  531.  
    },
  532.  
     
  533.  
     
  534.  
    vertexShader,
  535.  
    fragmentShader,
  536.  
    blending: THREE.AdditiveBlending,
  537.  
    depthTest: false,
  538.  
    transparent: true,
  539.  
    vertexColors: true
  540.  
    });
  541.  
     
  542.  
     
  543.  
    const geometry = new THREE.BufferGeometry();
  544.  
    const positions = [];
  545.  
    const colors = [];
  546.  
    const sizes = [];
  547.  
     
  548.  
    const color = new THREE.Color();
  549.  
     
  550.  
    for (let i = 0; i < totalPoints; i++) {
  551.  
    const [x, y, z] = [rand(-25, 25), 0, rand(-150, 15)];
  552.  
    positions.push(x);
  553.  
    positions.push(y);
  554.  
    positions.push(z);
  555.  
     
  556.  
    color.set(randChoise(["#93abd3", "#f2f4c0", "#9ddfd3"]));
  557.  
     
  558.  
    colors.push(color.r, color.g, color.b);
  559.  
    sizes.push(1);
  560.  
    }
  561.  
     
  562.  
    geometry.setAttribute(
  563.  
    "position",
  564.  
    new THREE.Float32BufferAttribute(positions, 3).setUsage(
  565.  
    THREE.DynamicDrawUsage));
  566.  
     
  567.  
     
  568.  
    geometry.setAttribute(
  569.  
    "customColor",
  570.  
    new THREE.Float32BufferAttribute(colors, 3));
  571.  
     
  572.  
    geometry.setAttribute("size", new THREE.Float32BufferAttribute(sizes, 1));
  573.  
     
  574.  
    const plane = new THREE.Points(geometry, shaderMaterial);
  575.  
     
  576.  
    plane.position.y = -8;
  577.  
    scene.add(plane);
  578.  
    }
  579.  
     
  580.  
    function addListners(camera, renderer, composer) {
  581.  
    document.addEventListener("keydown", e => {
  582.  
    const { x, y, z } = camera.position;
  583.  
    console.log(`camera.position.set(${x},${y},${z})`);
  584.  
    const { x: a, y: b, z: c } = camera.rotation;
  585.  
    console.log(`camera.rotation.set(${a},${b},${c})`);
  586.  
    });
  587.  
     
  588.  
    window.addEventListener(
  589.  
    "resize",
  590.  
    () => {
  591.  
    const width = window.innerWidth;
  592.  
    const height = window.innerHeight;
  593.  
     
  594.  
    camera.aspect = width / height;
  595.  
    camera.updateProjectionMatrix();
  596.  
     
  597.  
    renderer.setSize(width, height);
  598.  
    composer.setSize(width, height);
  599.  
    },
  600.  
    false);
  601.  
     
  602.  
    }
  603.  
    </script>
  604.  
     
  605.  
    </body>
  606.  
     
  607.  
    </html>
 

WebSocket:实现实时双向数据传输的Web通信协议

前端达人

 

前言

在当今互联网时代,实时通信已成为很多应用的需求。为了满足这种需求,WebSocket协议被设计出来。WebSocket是一种基于TCP议的全双工通信协议,通过WebSocket,Web应用程序可以与服务器建立持久的连接,实现实时双向数据输,提供极低的延迟和高效的数据传输。


WebSocket原理

  • HTTP请求-响应协议

在理解WebSocket原理之前,我们需要了解HTTP请求-响应协议。HTTP是一种无状态的请求-响应协议,客户端通过发送HTTP请求到服务器,服务器接收并处理请求,并返回HTTP响应给客户端。但是,在传统的HTTP协议中,客户端只能发送请求,而服务器只能通过响应来处理客户端的请求。

  • WebSocket协议

WebSocket协议是在HTTP协议的基础上进行扩展的。在建立WebSocket连接时,客户端首先发送一个HTTP请求到服务器,并将Upgrade头部字段设置为"websocket",表示希望升级到WebSocket协议。服务器接收到这个请求后,如果支持WebSocket协议,会返回一个状态码101 Switching Protocols的HTTP响应,并通过Upgrade头部字段将连接升级为WebSocket连接。

升级完成后,客户端和服务器之间的通信不再遵循HTTP请求-响应模式,而是通过WebSocket协议进行双向的实时通信。客户端和服务器可以直接发送消息给对方,不需要等待对方的请求。


如何使用WebSocket

建立WebSocket连接:

要建立WebSocket连接,需要在客户端和服务器之间进行系列的握手操作。下面是详细的代码教程,示了如何在Web应用程序中建立WebSocket连接。

在户端(JavaScript):

// 创建WebSocket对象并指定服务器地址
var socket = new WebSocket("ws://example.com/socket");

// 监听连接建立事件
socket.onopen = function() {
console.log("WebSocket连接已建立");
// 在连接建立后,可以发送消息到服务器
socket.send("Hello Server!");
};


// 监听接收到服务器发送的消息
socket.onmessage = function(event) {
var message = event.data;
console.log("接收到服务器发送的消息:" + message);
};


// 监听连接关闭事件
socket.onclose = function(event) {
console.log("WebSocket连接已关闭");
};


// 监听连接错误事件
socket.onerror = function(event) {
console.error("WebSocket连接错误:" + event};

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

在服务器端(示例使用Node.js):

const WebSocket = require("ws");

// 创建WebSocket服务器
const wss = new WebSocket.Server({ port: 8080 });


// 监听连接建立事件
wss.on("connection", function(socket) {
console.log("WebSocket连接已建立");


// 监听接收到客户端发送的消息
socket.on("message", function(message) {
console.log("接收到户端发送的消息:" + message);


<span class="token comment">// 向客户端发送消息</span>
socket<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">"Hello Client!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

});


// 监听连接关闭事件
socket.on("close", function() {
console.log("WebSocket连接已关闭");
});
});

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

在以上代码中,客户端通过创建WebSocket对象,并指定服务器地址"ws://example.com/socket"来建立WebSocket连接。同时,客户端通过监听onopen事件,可以在连接建立后发送消息到服务器。服务器端使用WebSocket.Server类创建WebSocket服务器,并监听"connection事件来处理连接建立后的操作。服务器端通过socket.on(“message”)来监听接收到客户端发送的消息,并通过socket.send()向客户端发送消息。

数据传输:

建立WebSocket连接后,客户端和服务器可以通过WebSocket对象进行双向的实时数据传输。下面是一个示例代码,演示了如何在客户端和服务器之间进行数据传输。

在客户端(JavaScript):

// 发送消息到服务器
socket.send("Hello Server!");

// 监听接收到服务器发送的消息
socket.onmessage = function(event) {
var message = event.data;
console.log("接收到服务器发送的消息:" + message);
};

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在服务器端(示例使用Node.js):

// 向客户端发送消息
socket.send("Hello Client!");

// 监听接收到客户端发送的消息
socket.on("message", function(message) {
console.log("接收到客户端发送的消息:" + message);
});

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在以上代码中,客户端通过调用socket.send()方法将消息发送到服务器,服务器通过socket.send()方法将消息发送到客户端。客户端通过监听socket.onmessage事件来接收服务器发送的消息,服务器通过监听socket.on("message")事件来接收客户端发送的消息。

通过以上代码示例,你可以详细了解如何使用WebSocket建立连接并进行数据传输。请注意,示例代码中使用的服务器地址和端口号需要根据实际情况进行修改。同时,你还可以在具体应用中根据需要使用WebSocket的其他方法和事件来实现更复杂的功能。


WebSocket的真实使用场景

即时通讯:

WebSocket非常适合用于即时通讯应用,因为它能够实现实时双向通信。以下是一个简单的即时聊天应用的代码教程。

在客户端(JavaScript):

// 创建WebSocket对象并指定服务器地址
var socket = new WebSocket("ws://example.com/socket");

// 监听连接建立事件
socket.onopen = function() {
console.log("WebSocket连接已建立");


// 监听文本框输入,按下Enter键时发送消息
var input = document.getElementById("input");
input.addEventListener("keyup", function(event) {
if (event.keyCode === 13) {
var message = input.value;
socket.send(message);
input.value = "";
}
});
};


// 监听接收到服务器发送的消息
socket.onmessage = function(event) {
var message = event.data;
console.log("接收到服务器发送的消息:" + message);


// 将接收到的消息显示在聊天窗口中
var chatWindow = document.getElementById("chatWindow");
chatWindow.innerHTML += "<p>" + message + "</p>";
};


// 监听连接关闭事件
socket.onclose = function(event) {
console.log("WebSocket连接已关闭");
};


// 监听连接错误事件
socket.onerror = function(event) {
console.error("WebSocket连接错误:" + event};

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

在服务器端(示例使用Node.js):

const WebSocket = require("ws");

// 创建WebSocket服务器
const wss = new WebSocket.Server({ port: 8080 });


// 监听连接建立事件
wss.on("connection", function(socket) {
console.log("WebSocket连接已建立");


// 监听接收到客户端发送的消息
socket.on("message", function(message) {
console.log("接收到客户端发送的消息:" + message);


<span class="token comment">// 向所有连接的客户端发送消息</span>
wss<span class="token punctuation">.</span>clients<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">client</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  client<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

});


// 监听连接关闭事件
socket.on("close", function() {
console.log("WebSocket连接已关闭");
});
});

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

在上述代码中,客户端通过创建WebSocket对象连接到服务器。输入框中的文本框用于录入要发送的消息,按下Enter键时会将消息发送给服务器。服务器接收到消息后,通过遍历所有连接的客户端,向每个客户端发送消息。

这样,多个客户端就可以实时地进行聊天,并且所有的消息都会实时地在各个客户端之间同步显示。

多人协作:

WebSocket还可用于多人协作应用,让多个用户可以实时地协同编辑文档或画布。以下是一个简单的代码教程。

在客户端(JavaScript):

// 创建WebSocket对象并指定服务器地址
var socket = new WebSocket("ws://example.com/socket");

// 监听连接建立事件
socket.onopen = function() {
console.log("WebSocket连接已建立");


// 监听文本框输入,按下Enter键时发送绘画指令
var canvas = document.getElementById("canvas");
canvas.addEventListener("mousedown", function(event) {
// 绘画指令的数据格式可以自定义,这里使用了简单的示例
var instruction = {
type: "draw",
position: {
x: event.clientX,
y: event.clientY
}
};
socket.send(JSON.stringify(instruction));
});
};


// 监听接收到服务器发送的消息
socket.onmessage = function(event) {
var message = JSON.parse(event.data);
console.log("接收到服务器发送的消息:" + message);


// 根据消息执行相应的操作,示例中处理了绘画指令
if (message.type === "draw") {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.arc(message.position.x, message.position.y, 5, 0, 2 * Math.PI);
ctx.fill();
}
};


// 监听连接关闭事件
socket.onclose = function(event) {
console.log("WebSocket连接已关闭");
};


// 监听连接错误事件
socket.onerror = function(event) {
console.error("WebSocket连接错误:" + event};

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

在服务器端(示例使用Node.js):

const WebSocket = require("ws");

// 创建WebSocket服务器
const wss = new WebSocket.Server({ port: 8080 });


// 监听连接建立事件
wss.on("connection", function(socket) {
console.log("WebSocket连接已建立");


// 监听接收到客户端发送的消息
socket.on("message", function(message) {
console.log("接收到客户端发送的消息:" + message);


<span class="token comment">// 向所有连接的客户端发送消息</span>
wss<span class="token punctuation">.</span>clients<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">client</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  client<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

});


// 监听连接关闭事件
socket.on("close", function() {
console.log("WebSocket连接已关闭");
});
});

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

在上述代码中,客户端通过创建WebSocket对象连接到服务器。当鼠标在画布上按下时,将绘画指令发送给服务器。服务器接收到绘画指令后,将指令广播给所有连接的客户端,并在各个客户端上进行绘画操作。

这样,多个用户就可以实时地协同编辑同一个画布或文档,所有的绘画指令都会即时同步在各个客户端之间。

实时数据更新:

WebSocket还可以用于实时数据更新应用,例如股票交易应用中的实时股票价格更新。以下是一个简单的代码教程。

在客户端(JavaScript):

// 创建WebSocket对象并指定服务器地址
var socket = new WebSocket("链接");

// 监听连接建立事件
socket.onopen = function() {
console.log("WebSocket连接已建立");
};


// 监听接收到服务器发送的消息
socket.onmessage = function(event) {
var message = JSON.parse(event.data);
console.log("接收到服务器发送的消息:" + message);


// 对接收到的实时数据进行处理
var stockPriceElement = document.getElementById("stockPrice");
stockPriceElement.innerText = message.price;
};


// 监听连接关闭事件
socket.onclose = function(event) {
console.log("WebSocket连接已关闭");
};


// 监听连接错误事件
socket.onerror = function(event) {
console.error("WebSocket连接错误:" + event};

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

在服务器端(示例使用Node.js):

const WebSocket = require("ws");

// 创建WebSocket服务器
const wss = new WebSocket.Server({ port: 8080 });


// 模拟实时股票价格更新
setInterval(function() {
var stockPrice = Math.random() * 100;


// 向所有连接的客户端发送实时数据
wss.clients.forEach(function(client) {
var data = {
price: stockPrice
};
client.send(JSON.stringify(data));
});
}, 2000);


// 监听连接建立事件
wss.on("connection", function(socket) {
console.log("WebSocket连接已建立");


// 初始化发送实时数据
var stockPrice = Math.random() * 100;
var data = {
price: stockPrice
};
socket.send(JSON.stringify(data));


// 监听连接关闭事件
socket.on("close", function() {
console.log("WebSocket连接已关闭");
});
});

 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

在上述代码中,客户端通过创建WebSocket对象连接服务器。服务器使用setInterval函数模拟实时股票价格的更新,并将更新的数据发送给所有连接的客户端。客户端监听接收到服务器发送的消息,并处理接收到的实时数据。

这样,在股票交易应用中,多个用户可以实时地接收和显示股票价格的更新信息。包括打游戏的时候,队友之间互相沟通,打字交流,或者走位,放技能等等,都是即时的。


WebSocket的优势与局限性

  • WebSocket的优势:
  • 双向实时通信:WebSocket提供了双向的实时信能力,客户端和服务器可以通过该协议进行双向数据传输,实时反馈更新信息,实现即时通讯、实时数据推送等功能。

  • 较低的延迟:与传统的HTTP请求相比,WebSocket降低了通信的开销,减少了传输和处理数据的延迟,因此可以更快进行实时数据传输。

  • 更高的性能:由于WebSocket使用较少的头部信息和更有效的消息传输格式,因此在相同带宽下可以传输更多的数据,提高了性能和效率。

  • 广泛的浏览器支持:WebSocket是HTML5的一部分,并且得到了大多数现代浏览器的支持,因此它可以在各种平台和设备上使用。

  • 连接保持:与传统的HTTP请求不同,WebSocket连接保持在建立之后,双方可以随时进行数据传输,避免了不必要的连接和断开操作。

  • WebSocket的局限性:
  • 兼容性问题:虽然现代浏览器广泛支持WebSocket,但在某些旧版本或特定设备上可能存在兼容性问题。为了兼容性,可以使用轮训技术(如长轮询)作为备选方案。

  • 部署和维护复杂性:WebSocket服务器的设置和配置可能比传统的Web服务器复杂一些,需要专门的服务器环境和配置。

  • 安全性问题:由于WebSocket是在HTTP协议的基础上建立的,它们共享相同的安全风险,例如跨站点脚本(XSS)和跨站请求伪造(CSRF)。因此,在使用WebSocket时需要考虑到安全性,并采取适当的安全措施。

  • 扩展问题:WebSocket协议还不支持像HTTP/2那样的一些高级特性,例如头部压缩和流量控制。在某些特殊情况下,可能需要通过其他方式实现这些功能。

尽管WebSocket具有上述局限性,但它仍然是实时通讯、实时数据传输和实时协作等场景下的首选协议,因为它具备了双向实时通信和较低延迟等一系列的优势。在开发时,需要根据具体需求和限制,综合考虑使用WebSocket的适用性。


结论

WebSocket是一种能够提供双向实时通信的协议,适用于需要实时数据传输和双向通信的场景。它具有较低的延迟、更高的性和广泛的浏览器持等优势,能够实现即时通讯、多人协和实时数据更新等功能。

然而,WebSocket也存在兼容性、部署和维护复杂性、安全性问题以及缺乏一些高级特性等局限性。在开发时,需要仔细考虑具体需求和限制,并必要时采取适当的解决方案。

总的来说,WebSocket在实时通信和实时数据传输方面具有明显的优势,是构建现代Web应用的重要工具之一。

蓝蓝设计(www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的大数据可视化界面设计B端界面设计桌面端界面设计APP界面设计图标定制用户体验设计交互设计UI咨询高端网站设计平面设计,以及相关的软件开发服务,咨询电话:01063334945。

关键词:UI咨询UI设计服务公司软件界面设计公司、界面设计公司、UI设计公司UI交互设计公司数据可视化设计公司用户体验公司高端网站设计公司

银行金融软件UI界面设计能源及监控软件UI界面设计气象行业UI界面设计轨道交通界面设计地理信息系统GIS UI界面设计航天军工软件UI界面设计医疗行业软件UI界面设计教育行业软件UI界面设计企业信息化UI界面设计、软件qt开发软件wpf开发软件vue开发

Vue2 watch监听props的值

前端达人

再次遇到监听子组件收到父组件传过来的值,如果这个值变化,页面中的值发现是不会跟着同步变化的。所以监听props中的值,一直监听。

 

代码:

 
  1.  
    props: {
  2.  
    start:{
  3.  
    type: String,
  4.  
    },
  5.  
    end:{
  6.  
    type: String,
  7.  
    }
  8.  
    },
 

 

 
  1.  
    computed:{
  2.  
    myStart:function(){
  3.  
    return this.start
  4.  
    },
  5.  
    myEnd:function(){
  6.  
    return this.end
  7.  
    }
  8.  
    },
  9.  
    watch: {
  10.  
    myStart:function(newVal){
  11.  
    if(newVal){
  12.  
    this.startTime=newVal
  13.  
    }
  14.  
    },
  15.  
    myEnd:function(newVal){
  16.  
    if(newVal){
  17.  
    this.endTime=newVal
  18.  
    }
  19.  
    },
  20.  

蓝蓝设计(www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的大数据可视化界面设计B端界面设计桌面端界面设计APP界面设计图标定制用户体验设计交互设计UI咨询高端网站设计平面设计,以及相关的软件开发服务,咨询电话:01063334945。

关键词:UI咨询UI设计服务公司软件界面设计公司、界面设计公司、UI设计公司UI交互设计公司数据可视化设计公司用户体验公司高端网站设计公司

银行金融软件UI界面设计能源及监控软件UI界面设计气象行业UI界面设计轨道交通界面设计地理信息系统GIS UI界面设计航天军工软件UI界面设计医疗行业软件UI界面设计教育行业软件UI界面设计企业信息化UI界面设计、软件qt开发软件wpf开发软件vue开发

什么是前端安全性(front-end security)?列举一些前端安全性的最佳实践

前端达人

前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发者,这里都将为你提供一个系统而又亲切的学习平台。在这个专栏中,我们将以问答形式每天更新,为大家呈现精选的前端知识点和常见问题解答。通过问答形式,我们希望能够更直接地回应读者们对于前端技术方面的疑问,并且帮助大家逐步建立起一个扎实的基础。无论是HTML、CSS、JavaScript还是各种常用框架和工具,我们将深入浅出地解释概念,并提供实际案例和练习来巩固所学内容。同时,我们也会分享一些实用技巧和最佳实践,帮助你更好地理解并运用前端开发中的各种技术。

无论你是寻找职业转型、提升技能还是满足个人兴趣,我们都将全力以赴,为你提供最优质的学习资源和支持。让我们一起探索Web开发的奇妙世界吧!加入前端入门之旅,成为一名出色的前端开发者! 让我们启航前端之旅!!!


前端安全性概述及最佳实践

前端安全性是指在前端开发中采取的一系列措施,旨在保护应用程序、用户数据以及用户隐私免受各种安全威胁。以下是一些前端安全性的最佳实践:

  1. HTTPS 使用:

    • 使用HTTPS协议确保数据在传输过程中的加密,防止中间人攻击。
  2. 内容安全策略(CSP):

    • 使用CSP来限制浏览器加载页面中的资源,防止恶意脚本注入。
  3. 跨站脚本攻击(XSS)防护:

    • 对用户输入和动态生成的内容进行合适的转义或编码。
    • 使用HTTP Only 标记来防止脚本操作 cookie。
  4. 跨站请求伪造(CSRF)防护:

    • 使用合适的令牌(CSRF Token)来验证请求的合法性。
  5. 安全的跨域资源共享(CORS)配置:

    • 限制允许访问资源的域,防止不受信任的域发起请求。
  6. 安全的第三方库和框架:

    • 使用官方版本的库和框架,避免使用已知的有安全漏洞的版本。
  7. 安全的存储和传输:

    • 避免在前端存储敏感信息,如密码,而应交由后端进行处理。
    • 在数据传输时使用加密算法,确保数据在传输过程中的保密性。
  8. 用户身份验证和授权:

    • 使用安全的身份验证方法,如OAuth或OpenID Connect。
    • 仅在有必要的情况下授予用户特定的权限。
  9. 不使用过期或不安全的特性:

    • 避免使用已经过时或不再维护的前端框架和库。
    • 避免使用不安全的浏览器特性,如弃用的插件。
  10. 前端路由安全:

    • 使用前端路由时,确保路由的访问权限得到合理管理,防止越权访问。
  11. 监测和报告安全事件:

    • 集成日志记录和监控机制,及时发现异常行为。
    • 实现安全事件报告,以便及时采取措施应对攻击。
  12. 教育和培训:

    • 对开发团队进行安全性培训,提高对潜在威胁的认识。
    • 定期进行代码审查,确保代码符合最佳安全实践。
  13. 安全头部的使用:

    • 使用HTTP头部来加强安全性,如Strict-Transport-Security(HSTS)。
  14. 定期进行安全性测试:

    • 进行定期的安全性测试,包括静态代码分析和渗透测试,以确保发现和修复潜在的安全漏洞。

这些最佳实践有助于构建更加安全、可靠的前端应用程序,减少潜在的攻击风险。前端安全性是一个不断演变的领域,开发者应该时刻关注新的安全威胁和最佳实践。


 

本专栏适用读者比较广泛,适用于前端初学者;或者没有学过前端对前端有兴趣的伙伴,亦或者是后端同学想在面试过程中能够更好的展示自己拓展一些前端小知识点,所以如果你具备了前端的基础跟着本专栏学习,也是可以很大程度帮助你查漏补缺,由于博主本人是自己再做内容输出,如果文中出现有瑕疵的地方各位可以通过主页的左侧联系我,我们一起进步,与此同时也推荐大家几份专栏,有兴趣的伙伴可以订阅一下:除了下方的专栏外大家也可以到我的主页能看到其他的专栏;

前端小游戏(免费)这份专栏将带你进入一个充满创意和乐趣的世界,通过利用HTML、CSS和JavaScript的基础知识,我们将一起搭建各种有趣的页面小游戏。无论你是初学者还是有一些前端开发经验,这个专栏都适合你。我们会从最基础的知识开始,循序渐进地引导你掌握构建页面游戏所需的技能。通过实际案例和练习,你将学会如何运用HTML来构建页面结构,使用CSS来美化游戏界面,并利用JavaScript为游戏添加交互和动态效果。在这个专栏中,我们将涵盖各种类型的小游戏,包括迷宫游戏、打砖块、贪吃蛇、扫雷、计算器、飞机大战、井字游戏、拼图、迷宫等等。每个项目都会以简洁明了的步骤指导你完成搭建过程,并提供详细解释和代码示例。同时,我们也会分享一些优化技巧和最佳实践,帮助你提升页面性能和用户体验。无论你是想寻找一个有趣的项目来锻炼自己的前端技能,还是对页面游戏开发感兴趣,前端小游戏专栏都会成为你的最佳选择

Vue3通透教程【从零到一】(付费) 欢迎来到Vue3通透教程!这个专栏旨在为大家提供全面的Vue3相关技术知识。如果你有一些Vue2经验,这个专栏都能帮助你掌握Vue3的核心概念和使用方法。我们将从零开始,循序渐进地引导你构建一个完整的Vue应用程序。通过实际案例和练习,你将学会如何使用Vue3的模板语法、组件化开发、状态管理、路由等功能。我们还会介绍一些高级特性,如Composition API和Teleport等,帮助你更好地理解和应用Vue3的新特性。在这个专栏中,我们将以简洁明了的步骤指导你完成每个项目,并提供详细解释和示例代码。同时,我们也会分享一些Vue3开发中常见的问题和解决方案,帮助你克服困难并提升开发效率。无论你是想深入学习Vue3或者需要一个全面的指南来构建前端项目,Vue3通透教程专栏都会成为你不可或缺的资源。

TypeScript入门指南(免费) 是一个旨在帮助大家快速入门并掌握TypeScript相关技术的专栏。通过简洁明了的语言和丰富的示例代码,我们将深入讲解TypeScript的基本概念、语法和特性。无论您是初学者还是有一定经验的开发者,都能在这里找到适合自己的学习路径。从类型注解、接口、类等核心特性到模块化开发、工具配置以及与常见前端框架的集成,我们将全面覆盖各个方面。通过阅读本专栏,您将能够提升JavaScript代码的可靠性和可维护性,并为自己的项目提供更好的代码质量和开发效率。让我们一起踏上这个精彩而富有挑战性的TypeScript之旅吧!

 

蓝蓝设计(www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的大数据可视化界面设计B端界面设计桌面端界面设计APP界面设计图标定制用户体验设计交互设计UI咨询高端网站设计平面设计,以及相关的软件开发服务,咨询电话:01063334945。

关键词:UI咨询UI设计服务公司软件界面设计公司、界面设计公司、UI设计公司UI交互设计公司数据可视化设计公司用户体验公司高端网站设计公司

银行金融软件UI界面设计能源及监控软件UI界面设计气象行业UI界面设计轨道交通界面设计地理信息系统GIS UI界面设计航天军工软件UI界面设计医疗行业软件UI界面设计教育行业软件UI界面设计企业信息化UI界面设计、软件qt开发软件wpf开发软件vue开发

前端学习大纲

前端达人

第一阶段:

  • HTML+CSS:

HTML进阶、CSS进阶、div+css布局、HTML+css整站开发、

  • JavaScript基础:

Js基础教程、js内置对象常用方法、常见DOM树操作大全、ECMAscript、DOM、BOM、定时器和焦点图。

  • JS基本特效:

常见特效、例如:tab、导航、整页滚动、轮播图、JS制作幻灯片、弹出层、手风琴菜单、瀑布流布局、滚动事件、滚差视图。

  • JS高级特征:

正则表达式、排序算法、递归算法、闭包、函数节流、作用域链、基于距离运动框架、面向对象基础、

  • JQuery:基础使用

悬着器、DOM操作、特效和动画、方法链、拖拽、变形、JQueryUI组件基本使用。

第二阶段:HTML5和移动Web开发

  • HTML5:

HTML5新语义标签、HTML5表单、音频和视频、离线和本地存储、SVG、Web Socket、Canvas.

  • CSS3:

CSS3新选择器、伪元素、脸色表示法、边框、阴影、background系列属性改变、Transition、动画、景深和深透、3D效果制作、Velocity.js框架、元素进场、出场策略、炫酷CSS3网页制作。

  • Bootstrap:

响应式概念、媒体查询、响应式网站制作、删格系统、删格系统原理、Bootstrap常用模板、LESS和SASS。

  • 移动Web开发:

跨终端WEB和主流设备简介、视口、流式布局、弹性盒子、rem、移动终端JavaScript事件、手机中常见JS效果制作、Zepto.js、手机聚划算页面、手机滚屏。

第三阶段:HTTP服务和AJAX编程

  • WEB服务器基础:

服务器基础知识、Apache服务器和其他WEB服务器介绍、Apache服务器搭建、HTTP介绍。

  • PHP基础:

PHP基础语法、使用PHP处理简单的GET或者POST请求、

  • AJAX上篇:

Ajax简介和异步的概念、Ajax框架的封装、XMLHttpRequest对象详细介绍方法、兼容性处理方法、Ajax框架的封装、Ajax中缓存问题、XML介绍和使用。

  • AJAX下篇:

JSON和JSON解析、数据绑定和模板技术、JSONP、跨域技术、图片预读取和lazy-load技术、JQuery框架中的AjaxAPI、使用Ajax实现爆布流案例额。

第四阶段:面向对象进阶

  • 面向对象终极篇:

从内存角度到理解JS面向对象、基本类型、复杂类型、原型链、ES6中的面向对象、属性读写权限、设置器、访问器。

  • 面向对象三大特征:

继承性、多态性、封装性、接口。

  • 设计模式:

面向对象编程思维、单例模式、工厂模式、策略模式、观察者模式、模板方法模式、代理模式、装饰者模式、适配器模式、面向切面编程。

第五阶段:封装一个属于自己的框架

  • 框架封装基础:

事件流、冒泡、捕获、事件对象、事件框架、选择框架。

  • 框架封装中级:

运动原理、单物体运动框架、多物体运动框架、运动框架面向对象封装。

  • 框架封装高级和补充:

JQuery框架雏形、可扩展性、模块化、封装属于传智自己的框架。

第六阶段:模块化组件开发

  • 面向组件编程:

面向组件编程的方式、面向组件编程的实现原理、面向组件编程实战、基于组件化思想开发网站应用程序。

  • 面向模块编程:

AMD设计规范、CMD设计规范、RequireJS,LoadJS、淘宝的SeaJS。

第七阶段:主流的流行框架

  • Web开发工作流:

GIT/SVN、Yeoman脚手架、NPM/Bower依赖管理工具、Grunt/Gulp/Webpack。

  • MVC/MVVM/MVW框架:

Angular.js、Backbone.js、Knockout/Ember。

  • 常用库:

React.js、Vue.js、Zepto.js。

第八阶段:HTML5原生移动应用开发

  • Cordova:

WebApp/NativeApp/HybirdApp简介、Cordova简介、与PhoneGap之间的关系、开发环境搭建、Cordova实战(创建项目,配置,编译,调试,部署发布)。

  • Ionic:

Ionic简介和同类对比、模板项目解析、常见组件及使用、结合Angular构建APP、常见效果(下拉刷新,上拉加载,侧滑导航,选项卡)。

  • React Native:

React Native简介、React Native环境配置、创建项目,配置,编译,调试,部署发布、原生模块和UI组件、原生常用API。

  • HTML5+:

HTML5+中国产业联盟、HTML5 Plus Runtime环境、HBuilder开发工具、MUI框架、H5+开发和部署。

第九阶段:   Node.js全栈开发:

  • 快速入门:

Node.js发展、生态圈、Io.js、Linux/Windows/OS X环境配置、REPL环境和控制台程序、异步编程,非阻塞I/O、模块概念,模块管理工具、开发流程,调试,测试。

  • 核心模块和对象:

全局对象global,process,console,util、事件驱动,事件发射器、加密解密,路径操作,序列化和反序列化、文件流操作、HTTP服务端与客户端、Socket.IO。

  • Web开发基础:

HTTP协议,请求响应处理过程、关系型数据库操作和数据访问、非关系型数据库操作和数据访问、原生的Node.js开发Web应用程序、Web开发工作流、Node.js开发Blog案例。

  • 快速开发框架:

Express简介+MVC简介、Express常用API、Express路由模块、Jade/Ejs模板引擎、使用Express重构Blog案例、Koa等其他常见MVC框架。

  • Node.js开发电子商务实战:

需求与设计、账户模块注册登录、会员中心模块、前台展示模块、购物车,订单结算、在线客服即时通讯模块。

MacOS查找各Python版本的路径

前端达人

MacOS自带Python路径为:/System/Library/Frameworks/Python.framework/Versions
自行安装Python路径为:/Library/Frameworks/Python.framework/Versions/
打开Terminal
切换工作路径:cd /System/Library/Frameworks/Python.framework/Versions/current/bin
打印相对路径Python版本:./python --version
打印当前用户Python版本:python --version

如下图可以看到,系统Python版本为2.7,当前用户Python为3.7

 

使用which命令查看各版本Python的文件路径

系统命令默认路径/usr/bin(系统预装的可执行文件,随系统升级而变化)
用户命令默认路径/usr/local/bin(用户安装的可执行文件,不随系统升级影响)
其中,usrUnix System Resource

可以看到/usr/bin中有python可执行命令,其版本为2.7.18,而/usr/local/bin则没有python,存放的是python3.7的执行命令

 

在Mac电脑上安装Python环境可以按照以下步骤进行操作:

步骤1: 下载Python安装包

访问Python官方网站(https://www.python.org/downloads/macos/)下载适用于Mac的Python安装包。根据你的操作系统版本选择合适的安装包,通常选择最新的稳定版本。
在这里插入图片描述

步骤2: 运行安装包

双击下载的Python安装包,会出现一个安装向导窗口。点击"Continue"继续安装。
在这里插入图片描述

步骤3: 配置安装选项

在安装向导窗口中,可以选择安装Python的位置和其他可选组件。通常建议保持默认设置,然后点击"Install"开始安装。

步骤4: 输入管理员密码

安装过程中,系统可能会要求输入管理员密码。输入密码并点击"Install Software"继续安装。

步骤5: 等待安装完成

安装过程可能需要一些时间,请耐心等待直到安装完成。

步骤6: 验证安装结果

安装完成后,打开终端应用程序(Terminal),输入以下命令验证Python安装是否成功:

python3 -V
  • 1

如果成功安装,终端会显示Python的版本号。

 

产品经理如何与工程师合作?我总结了4个方面!|北京蓝蓝UI设计公司

周周

在产品线或者项目组中,开发工程师绝对是最大的群体,包含前端开发、后端开发、测试等岗位。之前做交互设计师时,跟开发人员直接的沟通并不多,主要在交互设计宣讲和还原度测试时有些接触。即使有些纠缠,也会通过产品经理进行协调,沟通的难度并不大。转岗产品经理后,主要沟通对象就变成了开发工程师。今天来聊聊我遇到过或合作过的“开发大佬”们。

干货!四个章节深度解析「组件」知识点|兰亭妙微UI设计公司

雪涛

干货!四个章节深度解析「组件」知识点|兰亭妙微UI设计公司


第一章:组件的定义和基本概念
在软件开发领域,组件是指独立的、可重用的软件模块,它们具有特定的功能和接口,可以被组合成更大的软件系统。组件可以是软件对象、类、库、模块或其他单位。它们通过定义输入和输出接口,以及实现特定功能来提供服务。
组件的基本概念包括以下几个方面:
1.1 组件容器:组件容器是一个环境,用于加载、管理和执行组件。容器提供对组件的生命周期管理、通信和部署支持。组件容器可以是运行时环境(如操作系统、应用服务器)或特定的框架(如Java EE容器、ASP.NET容器)。
1.2 组件接口:组件接口定义了组件对外提供的服务和合约。它包括输入参数、输出结果以及可能的异常。接口可以通过编程语言的接口、类、方法或其他机制来定义。
1.3 组件协作:组件可以通过协作来完成更复杂的任务。协作可以通过组件之间的接口调用、事件触发、消息传递等方式进行。协作可以实现任务的拆分、并行处理和功能扩展。
1.4 组件复用:组件的重要特性是可复用性。组件的设计和实现应该考虑到复用的需求,使其可以在不同的上下文中被重复使用。组件复用可以提高开发效率、降低维护成本,并促进软件系统的生态系统发展。
第二章:组件化开发和架构模式
2.1 组件化开发:组件化开发是一种软件开发方法,通过将软件系统划分为独立的组件来提高开发效率和质量。组件化开发促进了模块化、可复用、可测试和可维护的代码编写。它还鼓励团队协作和并行开发。
2.2 组件化架构模式:组件化架构模式是一种组织和管理组件的方式。常见的组件化架构模式包括面向服务架构(SOA)、微服务架构和组件协作模式等。这些架构模式通过定义组件之间的接口、通信和协议,实现了松耦合、可扩展和可替换的软件系统。

第三章:组件的优势和挑战
3.1 组件的优势:组件化开发具有许多优势。首先,它提供了代码重用和模块化的机制,减少了开发工作量和维护成本。其次,组件可以提供标准化的接口,促进了团队协作和模块复用。此外,组件可以独立测试和部署,提高了系统的可靠性和可扩展性。
3.2 组件的挑战:尽管组件化开发具有许多优势,但也存在一些挑战。首先,组件的设计和实现需要额外的工作和时间。其次,组件之间的协作和通信涉及到复杂的依赖关系和调试过程。此外,组件的版本管理和升级可能导致一些兼容性和稳定性的问题。
第四章:组件化开发实践和案例分析
4.1 组件化开发实践:组件化开发需要结合具体的技术和工具来实现。常见的组件化开发实践包括使用面向对象编程、设计模式、依赖注入和模块化打包工具等。此外,组件化开发还需要规范和标准来指导开发和集成。
4.2 组件化开发案例分析:组件化开发已经在软件开发领域得到广泛应用。例如,Android开发中的组件化架构、Java EE中的Enterprise JavaBean、.NET中的组件模型等。这些案例提供了关于组件化开发的实践经验和最佳实践。

蓝蓝设计,工作室2008年开始,2011年正式成立北京兰亭妙微科技有限公司,主创清华团队,专注软件和互联网ui设计开发。擅长企业信息化管理、监控、大数据软件UIUE咨询和设计开发服务。立足UI,一直在学习进步。
蓝蓝设计,秉承设计优秀,不断超越的理念,诚信敬业、专业耐心的工作作风,进行设计服务创新,帮助企业进行软件和互联网产品的界面设计及开发升级,提供卓越的解决方案。对软件界面用户体验与交互设计与实现,国际化标准和流行趋势,进行不断的研究和实践,拥有丰富的解决问题经验。

让用户输密码的正确姿势!简化密码设计的三个小秘籍

雪涛

让用户输密码的正确姿势!简化密码设计的三个小秘籍

2023-06-28 15:50北京北京兰亭妙微科技有限公司官方帐号

随着互联网的普及和数字化时代的来临,密码的重要性不言而喻。然而,很多人在设计密码时往往面临记忆难题和安全性问题。为了帮助用户设计更简化且安全的密码,本文将介绍三个小秘籍。

一、使用密码管理工具

密码管理工具是一种方便且安全的方式来管理和存储密码。它们通常提供加密的存储空间,可以储存各种账户的用户名和密码。用户只需记住一个主密码,就能够访问和管理所有其他密码。这样,用户可以选择更复杂、更安全的密码,而不必担心记忆的问题。此外,密码管理工具通常还提供自动生成密码的功能,确保密码的随机性和安全性。一些常见的密码管理工具包括LastPass、1Password和Keepass等。

二、使用短语或句子作为密码

传统的密码通常由字符、数字和特殊符号组成,很难记忆且容易被猜测。相比之下,使用短语或句子作为密码可以更容易记住且更安全。选择一个有意义的短语或句子,并将其转化为密码。例如,"ILoveToTravelTheWorld!",这个短语可以转化为密码"Ilv2ttw!"。这样的密码不仅容易记忆,而且由于包含了大小写字母、数字和特殊符号,具备了一定的安全性。

三、使用多因素身份验证

多因素身份验证是一种提高账户安全性的重要方式。除了使用密码外,多因素身份验证要求用户提供第二个验证因素,如手机验证码、指纹识别或硬件安全密钥等。这样,即使密码被泄露,黑客也无法轻易访问账户。许多在线服务提供了多因素身份验证选项,用户应该积极开启并使用这个功能。

综上所述,设计简化且安全的密码并不是一件困难的事情。通过使用密码管理工具、使用短语或句子作为密码以及使用多因素身份验证,用户可以更好地保护自己的账户安全。重要的是,用户应该时刻保持警惕,定期更换密码,并避免在多个账户中使用相同的密码,以确保个人信息的安全。

今日分享这篇文章是蓝蓝设计的原创文章,未来将会持续在平台上分享关于设计行业的文章。此外蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,添加vx蓝小助ben_lanlan,报下信息,蓝小助会请您入群。同时添加蓝小助我们将会为您提供优秀的设计案例和设计素材等,欢迎您加入噢~~希望得到建议咨询、商务合作,也请与我们联系。

蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务、UI设计公司、界面设计公司、UI设计服务公司、数据可视化设计公司、UI交互设计公司、高端网站设计公司、UI咨询、用户体验公司、软件界面设计公司

js谷歌地图 根据国家添加不同的点击事件

前端达人

以下是在 JavaScript 和 Google 地图 API 中添加点击事件,根据国家进行不同操作的示例代码:


//创建地图对象
var map = new google.maps.Map(document.getElementById('map'), {
  zoom: 4,
  center: {lat: 37.0902, lng: -95.7129}
});

//创建信息窗口(infowindow)
var infowindow = new google.maps.InfoWindow();

//创建一个数组来存储标记
var markers = [];

//为每个国家添加点击事件
google.maps.event.addListener(map, 'click', function(event) {
  //获取点击位置的经纬度坐标
  var latLng = event.latLng;

  //使用地理编码器(geocoder)将经纬度坐标转换为地址信息
  var geocoder = new google.maps.Geocoder();
  geocoder.geocode({'location': latLng}, function(results, status) {
    if (status === 'OK') {
      if (results[0]) {
        //获取点击位置所在的国家名称
        var countryName = '';
        for (var i = 0; i < results[0].address_components.length; i++) {
          var component = results[0].address_components[i];
          if (component.types.indexOf('country') !== -1) {
            countryName = component.long_name;
            break;
          }
        }

        //根据国家名称执行相应操作
        switch (countryName) {
          case 'China':
            alert('您点击了中国');
            break;
          case 'United States':
            alert('您点击了美国');
            break;
          default:
            alert('您点击了' + countryName);
        }

        //创建标记并将其添加到地图上
        var marker = new google.maps.Marker({
          position: latLng,
          map: map
        });

蓝蓝设计建立了UI设计分享群,每天会分享国内外的一些优秀设计,如果有兴趣的话,可以进入一起成长学习,请加微信ban_lanlan,报下信息,蓝小助会请您入群。欢迎您加入噢~~ 希望得到建议咨询、商务合作,也请与我们联系01063334945。  分享此文一切功德,皆悉回向给文章原作者及众读者. 免责声明:蓝蓝设计尊重原作者,文章的版权归原作者。如涉及版权问题,请及时与我们取得联系,我们立即更正或删除。  蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务UI设计公司、界面设计公司、UI设计服务公司、数据可视化设计公司、UI交互设计公司、高端网站设计公司、UI咨询、用户体验公司、软件界面设计公司 

日历

链接

blogger

蓝蓝 http://www.lanlanwork.com

存档