স্ক্রোল এ সম্পর্কিত থেকে স্থির থেকে এলিমেন্ট


9

আমি একটি মোড়ক তৈরি করেছি যাতে আমি তাদের এয়ারপডস প্রো পৃষ্ঠায় অ্যাপলের মতো একই প্রভাব অ্যানিমেট করেছি । এটি মূলত একটি ভিডিও, যখন আমি ভিডিওটি কিছুটা প্লে করে খেলি। ভিডিওর অবস্থান স্থির করা হয়েছে যাতে পাঠ্যটি সুন্দরভাবে তার উপরে স্ক্রোল করে। তবে, পাঠ্যটি কেবল তখনই দৃশ্যমান হয় যখন নির্দিষ্ট বিভাগের (পাঠ্য-প্রদর্শন) অফসেটের মধ্যে থাকে।

অংশটি ভাল কাজ করে। এখন আমি চাই যে ব্যবহারকারী যখন ভিডিওর শেষে স্ক্রোল করে এবং এভাবে অ্যানিমেশনটি শেষ হয়, তখন ভিডিও-প্রভাব-র‌্যাপার একটি নির্দিষ্ট অবস্থান থেকে আপেক্ষিক অবস্থানে চলে যায়। সুতরাং যে ওয়েবসাইট ভিডিও অ্যানিমেশন পর স্বাভাবিকভাবে এটা বিষয়বস্তু স্ক্রল হবে

জেএসফিডল কোড + ডেমো

এটি আমি ইতিমধ্যে যা চেষ্টা করেছি তার একটি উদাহরণ:

        //If video-animation ended: Make position of video-wrapper relative to continue scrolling
        if ($(window).scrollTop() >= $("#video-effect-wrapper").height()) {
            $(video).css("position", "relative");
            $("#video-effect-wrapper .text").css("display", "none");
        }

এই ধরণের কাজ ... তবে মসৃণ বাদে সবকিছুই। এবং ওয়েবপৃষ্ঠাটি পিছন দিকে বিপরীত করাও সম্ভব দরকার।

এই সমস্যাটি সমাধান করার চেষ্টা করার সময় আমি যে সমস্যার মুখোমুখি হয়েছিলাম:

  • স্ক্রোলিং, এবং স্থির থেকে আপেক্ষিক রূপান্তর প্রাকৃতিক এবং মসৃণ বোধ করা প্রয়োজন
  • মোড়ক নিজেই স্থির হয় নি এবং এতে টেক্সট উপাদান রয়েছে, ভিডিওটি ঠিক করা হয়েছে যাতে টেক্সট উপাদানগুলি ভিডিও উপাদানটির উপর দিয়ে যেতে পারে (প্রভাব তৈরি করে)। এই .text উপাদানগুলির সমাধান সন্ধান করার চেষ্টা করার কারণে সমস্যা দেখা দেয়

উত্তর:


3

এয়ারপডস প্রো পৃষ্ঠায় কিছু বিপরীত প্রকৌশল করার সময় , আমরা লক্ষ্য করেছি যে অ্যানিমেশনটি একটি ব্যবহার করে না video, তবে একটি canvas। বাস্তবায়ন নিম্নরূপ:

  • এইচটিটিপি 2 এর উপরে প্রায় 1500 টি চিত্র প্রিলোড করুন, আসলে অ্যানিমেশনের ফ্রেম
  • আকারে চিত্রের একটি অ্যারে তৈরি করুন HTMLImageElement
  • প্রতিটি scrollডিওএম ইভেন্টের প্রতিক্রিয়া জানান এবং সাথে একটি নিকটতম চিত্রের সাথে সম্পর্কিত অ্যানিমেশন ফ্রেমের জন্য অনুরোধ করুনrequestAnimationFrame
  • অ্যানিমেশন ফ্রেমে কলব্যাকের জন্য অনুরোধ জানায়, ব্যবহার করে চিত্রটি প্রদর্শিত করুন ctx.drawImage( ctxএর 2dপ্রসঙ্গ হতে পারে)canvas উপাদান)

দ্য requestAnimationFrameফাংশন আপনি একটি বাধামুক্ত প্রভাব অর্জন যেমন ফ্রেম ডেফার্ড এবং টার্গেট পর্দার রেট "প্রতি সেকেন্ডে ফ্রেম" সঙ্গে সিঙ্ক্রোনাইজ করতে সাহায্য করা উচিত।

কোনও স্ক্রোল ইভেন্টে ফ্রেমটি কীভাবে সঠিকভাবে প্রদর্শন করতে হয় সে সম্পর্কে আরও তথ্যের জন্য আপনি এটি পড়তে পারেন: https://developer.mozilla.org/en-US/docs/Web/API/Docament/scroll_event

বলা হচ্ছে, আপনার মূল সমস্যা সম্পর্কে, আমার একটি কার্যনির্বাহী সমাধান রয়েছে যা এতে অন্তর্ভুক্ত করে:

  • videoউপাদানগুলির চেয়ে একই উচ্চতা এবং প্রস্থের একটি স্থানধারক তৈরি করা । এর উদ্দেশ্যটি হ'ল ভিডিওটি এড়ানো যখন সেট করা থাকে তখন বাকি এইচটিএমএলকে ওভারল্যাপ করাabsolute অবস্থানটি
  • মধ্যে scrollঘটনা কলব্যাক যখন স্থানধারক ভিউপোর্ট উপরের ছুঁয়েছে, এর ভিডিওর অবস্থান সেট absolute, এবং ডানtop মূল্য

ধারণাটি হ'ল ভিডিওটি সর্বদা প্রবাহের বাইরে থাকে এবং নীচে স্ক্রোল করার সময় সঠিক মুহুর্তে স্থানধারকের উপরে স্থান নেয়।

এখানে জাভাস্ক্রিপ্ট:

//Get video element
let video = $("#video-effect-wrapper video").get(0);
video.pause();

let topOffset;

$(window).resize(onResize);

function computeVideoSizeAndPosition() {
    const { width, height } = video.getBoundingClientRect();
    const videoPlaceholder = $("#video-placeholder");
    videoPlaceholder.css("width", width);
    videoPlaceholder.css("height", height);
    topOffset = videoPlaceholder.position().top;
}

function updateVideoPosition() {
    if ($(window).scrollTop() >= topOffset) {
        $(video).css("position", "absolute");
        $(video).css("left", "0px");
        $(video).css("top", topOffset);
    } else {
        $(video).css("position", "fixed");
        $(video).css("left", "0px");
        $(video).css("top", "0px");
    }
}

function onResize() {
    computeVideoSizeAndPosition();
    updateVideoPosition();
}

onResize();

//Initialize video effect wrapper
$(document).ready(function () {

    //If .first text-element is set, place it in bottom of
    //text-display
    if ($("#video-effect-wrapper .text.first").length) {
        //Get text-display position properties
        let textDisplay = $("#video-effect-wrapper #text-display");
        let textDisplayPosition = textDisplay.offset().top;
        let textDisplayHeight = textDisplay.height();
        let textDisplayBottom = textDisplayPosition + textDisplayHeight;

        //Get .text.first positions
        let firstText = $("#video-effect-wrapper .text.first");
        let firstTextHeight = firstText.height();
        let startPositionOfFirstText = textDisplayBottom - firstTextHeight + 50;

        //Set start position of .text.first
        firstText.css("margin-top", startPositionOfFirstText);
    }
});

//Code to launch video-effect when user scrolls
$(document).scroll(function () {

    //Calculate amount of pixels there is scrolled in the video-effect-wrapper
    let n = $(window).scrollTop() - $("#video-effect-wrapper").offset().top + 408;
    n = n < 0 ? 0 : n;

    //If .text.first is set, we need to calculate one less text-box
    let x = $("#video-effect-wrapper .text.first").length == 0 ? 0 : 1;

    //Calculate how many percent of the video-effect-wrapper is currenlty scrolled
    let percentage = n / ($(".text").eq(1).outerHeight(true) * ($("#video-effect-wrapper .text").length - x)) * 100;
    //console.log(percentage);
    //console.log(percentage);

    //Get duration of video
    let duration = video.duration;

    //Calculate to which second in video we need to go
    let skipTo = duration / 100 * percentage;

    //console.log(skipTo);

    //Skip to specified second
    video.currentTime = skipTo;

    //Only allow text-elements to be visible inside text-display
    let textDisplay = $("#video-effect-wrapper #text-display");
    let textDisplayHeight = textDisplay.height();
    let textDisplayTop = textDisplay.offset().top;
    let textDisplayBottom = textDisplayTop + textDisplayHeight;
    $("#video-effect-wrapper .text").each(function (i) {
        let text = $(this);

        if (text.offset().top < textDisplayBottom && text.offset().top > textDisplayTop) {
            let textProgressPoint = textDisplayTop + (textDisplayHeight / 2);
            let textScrollProgressInPx = Math.abs(text.offset().top - textProgressPoint - textDisplayHeight / 2);
            textScrollProgressInPx = textScrollProgressInPx <= 0 ? 0 : textScrollProgressInPx;
            let textScrollProgressInPerc = textScrollProgressInPx / (textDisplayHeight / 2) * 100;

            //console.log(textScrollProgressInPerc);
            if (text.hasClass("first"))
                textScrollProgressInPerc = 100;

            text.css("opacity", textScrollProgressInPerc / 100);
        } else {
            text.css("transition", "0.5s ease");
            text.css("opacity", "0");
        }
    });

    updateVideoPosition();

});

এইচটিএমএল:

<div id="video-effect-wrapper">
    <video muted autoplay>
        <source src="https://ndvibes.com/test/video/video.mp4" type="video/mp4" id="video">
    </video>
    <div id="text-display"/>
    <div class="text first">
        Scroll down to test this little demo
    </div>
    <div class="text">
        Still a lot to improve
    </div>
    <div class="text">
        So please help me
    </div>
    <div class="text">
        Thanks! :D
    </div>
</div>
<div id="video-placeholder">

</div>
<div id="other-parts-of-website">
    <p>
        Normal scroll behaviour wanted.
    </p>
    <p>
        Normal scroll behaviour wanted.
    </p>
    <p>
        Normal scroll behaviour wanted.
    </p>
    <p>
        Normal scroll behaviour wanted.
    </p>
    <p>
        Normal scroll behaviour wanted.
    </p>
    <p>
        Normal scroll behaviour wanted.
    </p>
</div>

আপনি এখানে চেষ্টা করতে পারেন: https://jsfiddle.net/crkj1m0v/3/


2
এই ধরণের অ্যানিমেশন কীভাবে প্রয়োগ করা যায় সে সম্পর্কে এটি আকর্ষণীয় এবং দরকারী পটভূমি হলেও এটি @ ওনিলের প্রশ্নের সাথে বিশেষভাবে প্রাসঙ্গিক বলে মনে হচ্ছে না, যা অ্যানিমেশনটি শেষ হয়ে গেলে পৃষ্ঠাটির স্ক্রোলিং পুনরায় শুরু করার জন্য সুনির্দিষ্ট। ওনিয়েল নোট হিসাবে, ইতিমধ্যে স্ক্রোলিং এবং প্লেব্যাক মধ্যে সমিতি কাজ করছে।
জেরেমি কেনি

1
অ্যাপল কীভাবে এটি করেছে তার অন্তর্দৃষ্টি তথ্যের জন্য ধন্যবাদ এবং সুন্দর এবং মসৃণ সমাধানের জন্য আরও বড় ধন্যবাদ!
ও'ইয়েল

1

আপনি যদি ব্যাক আপটি স্ক্রোল করার সাথে সাথে ভিডিওটি আবার তালাবন্ধ হয়ে যেতে চান তবে আপনি যে জায়গা থেকে স্যুইচ করেছেন সেই স্থানটি চিহ্নিত fixedকরতে হবে relative

//Get video element
let video = $("#video-effect-wrapper video").get(0);
video.pause();

let videoLocked = true;
let lockPoint = -1;
const vidHeight = 408;

//Initialize video effect wrapper
$(document).ready(function() {

  const videoHeight = $("#video-effect-wrapper").height();

  //If .first text-element is set, place it in bottom of
  //text-display
  if ($("#video-effect-wrapper .text.first").length) {
    //Get text-display position properties
    let textDisplay = $("#video-effect-wrapper #text-display");
    let textDisplayPosition = textDisplay.offset().top;
    let textDisplayHeight = textDisplay.height();
    let textDisplayBottom = textDisplayPosition + textDisplayHeight;

    //Get .text.first positions
    let firstText = $("#video-effect-wrapper .text.first");
    let firstTextHeight = firstText.height();
    let startPositionOfFirstText = textDisplayBottom - firstTextHeight + 50;

    //Set start position of .text.first
    firstText.css("margin-top", startPositionOfFirstText);
  }


  //Code to launch video-effect when user scrolls
  $(document).scroll(function() {

    //Calculate amount of pixels there is scrolled in the video-effect-wrapper
    let n = $(window).scrollTop() - $("#video-effect-wrapper").offset().top + vidHeight;
    n = n < 0 ? 0 : n;
    // console.log('n: ' + n);

    //If .text.first is set, we need to calculate one less text-box
    let x = $("#video-effect-wrapper .text.first").length == 0 ? 0 : 1;

    //Calculate how many percent of the video-effect-wrapper is currenlty scrolled
    let percentage = n / ($(".text").eq(1).outerHeight(true) * ($("#video-effect-wrapper .text").length - x)) * 100;
    //console.log(percentage);

    //Get duration of video
    let duration = video.duration;

    //Calculate to which second in video we need to go
    let skipTo = duration / 100 * percentage;

    //console.log(skipTo);

    //Skip to specified second
    video.currentTime = skipTo;

    //Only allow text-elements to be visible inside text-display
    let textDisplay = $("#video-effect-wrapper #text-display");
    let textDisplayHeight = textDisplay.height();
    let textDisplayTop = textDisplay.offset().top;
    let textDisplayBottom = textDisplayTop + textDisplayHeight;
    $("#video-effect-wrapper .text").each(function(i) {
      let text = $(this);

      if (text.offset().top < textDisplayBottom && text.offset().top > textDisplayTop) {
        let textProgressPoint = textDisplayTop + (textDisplayHeight / 2);
        let textScrollProgressInPx = Math.abs(text.offset().top - textProgressPoint - textDisplayHeight / 2);
        textScrollProgressInPx = textScrollProgressInPx <= 0 ? 0 : textScrollProgressInPx;
        let textScrollProgressInPerc = textScrollProgressInPx / (textDisplayHeight / 2) * 100;

        //console.log(textScrollProgressInPerc);
        if (text.hasClass("first"))
          textScrollProgressInPerc = 100;

        text.css("opacity", textScrollProgressInPerc / 100);
      } else {
        text.css("transition", "0.5s ease");
        text.css("opacity", "0");
      }
    });


    //If video-animation ended: Make position of video-wrapper relative to continue scrolling
    if (videoLocked) {
      if ($(window).scrollTop() >= videoHeight) {
        $('video').css("position", "relative");
        videoLocked = false;
        lockPoint = $(window).scrollTop() - 10;
        // I gave it an extra 10px to avoid flickering between locked and unlocked.
      }
    } else if ($(window).scrollTop() < lockPoint) {
      $('video').css("position", "fixed");
      videoLocked = true;
    }

  });




});
body {
  margin: 0;
  padding: 0;
  background-color: green;
}

#video-effect-wrapper {
  height: auto;
  width: 100%;
}

#video-effect-wrapper video {
  width: 100%;
  height: 100%;
  position: fixed;
  top: 0;
  left: 0;
  z-index: -2;
  object-fit: cover;
}

#video-effect-wrapper::after {
  content: "";
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: block;
  background: #000000;
  background: linear-gradient(to top, #434343, #000000);
  opacity: 0.4;
  z-index: -1;
}

#video-effect-wrapper .text {
  color: #FFFFFF;
  font-weight: bold;
  font-size: 3em;
  width: 100%;
  margin-top: 50vh;
  font-family: Arial, sans-serif;
  text-align: center;
  opacity: 0;
  /*
                background-color: blue;
                */
}

#video-effect-wrapper .text.first {
  margin-top: 50vh;
  opacity: 1;
}

#video-effect-wrapper .text:last-child {
  /*margin-bottom: 100vh;*/
  margin-bottom: 50vh;
}

#video-effect-wrapper #text-display {
  display: block;
  width: 100%;
  height: 225px;
  position: fixed;
  top: 50%;
  transform: translate(0, -50%);
  z-index: -1;
  /*
                background-color: red;
                */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="video-effect-wrapper">
  <video muted autoplay>
            <source src="https://ndvibes.com/test/video/video.mp4" type="video/mp4" id="video">
          </video>

  <div id="text-display"></div>
  <div class="text first">
    Scroll down to test this little demo
  </div>
  <div class="text">
    Still a lot to improve
  </div>
  <div class="text">
    So please help me
  </div>
  <div class="text">
    Thanks! :D
  </div>
</div>

<div id="other-parts-of-website">
  <p>
    Normal scroll behaviour wanted.
  </p>
  <p>
    Normal scroll behaviour wanted.
  </p>
  <p>
    Normal scroll behaviour wanted.
  </p>
  <p>
    Normal scroll behaviour wanted.
  </p>
  <p>
    Normal scroll behaviour wanted.
  </p>
  <p>
    Normal scroll behaviour wanted.
  </p>
</div>


হ্যালো আপনার উত্তরের জন্য ধন্যবাদ। এই সমাধানটি কাছে পেয়েছে তবে আপনার কোডের সাথে আমি এখনও একটি বড় সমস্যার মুখোমুখি হয়েছি: ভিডিও শেষ হওয়ার সাথে সাথে ভিডিও-উপাদানটির অবস্থান স্থির হয়ে যায়, তবে সবুজ পটভূমিতে এখনও সাদা অনুচ্ছেদ রয়েছে। ভিডিও # অ্যানিমেশনের পরে ডিভি # অন্যান্য অংশের-ওয়েবসাইটটি প্রথম কনটেন্ট হওয়া উচিত।
ও'ইয়েল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.