<script src="../lib/scripts/jquery/jquery.min.js" type="text/javascript"></script>
 
 
<!-- Container (jumbotron ) -->
<div class="jumbotron text-center" style="height:100vh" hidden=true>
 <div class="bg"></div>
  <h2>Professional microgrid energy storage solution provider</h2> 
</div>
<!-- Container (jumbotron ) -->
 
 
<div class="container-fluid" id="sequence-container-1" style=" position: relative;  min-height: 682vh;  margin-bottom: 2rem;  overflow: visible;">
 <div class="container scroll-container">
<!--   <div class="spacer" style="height: 80vh"></div> -->
  <section class="scroll-sequence__container tree-container">
    <div class="scroll-sequence tree-sequence"></div>
    <div class="scroll-sequence__content">
      <div class="speak">
       <p style="font-size:2.5em">Smarten Your Electricity</p></br>
      Smart Power, Empowering the Future
      </div>
      <div class="speak">
      With a commitment to green manufacturing, serving globally, promoting the large-scale application of renewable energy, and enabling a low-carbon future.
      </div>
      <div class="speak">
      Through technological innovation, continuously pushing the boundaries of technology to develop smarter, more efficient, and more reliable energy conversion systems.
      </div>
       <div class="speak">
      Innovation-driven, open and progressive, collaborative growth, and co-creating value
      </div>
  </section>
<!--   <div class="spacer"></div> -->
 
</div>
</div>
 
 
 
<!-- Container (About our company ) -->
 <div class="container-fluid container-padding text-center">
  <div class="text-center">
    <h2>About our company</h2>
  </div>
</div>
 
 
<!-- Container (Important Milestones) -->
  <div class="container-fluid container-padding text-center">
    <div class="col-md-4" >      
      <i class="fa fa-hand-o-right fa-5x"></i>
      <h1><span class="counter"  style="color: #19adb2">2019</span></h1>
      <h3>Business Started</h3>
    </div> 
    <div class="col-md-4">
      <i class="fa fa-lightbulb-o fa-5x"></i>
      <h1><span class="counter" style="color: #19adb2">20+</span></h1>
      <h3>Patents</h3>
    </div>
    <div class="col-md-4">
      <i class="fa fa-cart-arrow-down fa-5x"></i>
      <h1><span class="counter"  style="color: #19adb2">14,000+</span></h1>
      <h3>SiC inverters delivered </h3>
    </div>
  </div>
 
 
 
  <!-- Container (History) -->
 <div class="container-fluid container-padding text-center mapWrapper">
<div class="mapWrapper">
	<div class="row"><!--
 --><div class="itemBar"><!--
	 --><div class="itemInfo"> Founding Team Established</div><!--
	 --><div class="itemDate">2019</div><!--
 --></div><!--
 --><div class="itemBar"><div class="itemInfo">R&D project officially launched</div><div class="itemDate">2020</div></div><!--
 --><div class="itemBar"><div class="itemInfo">Building the Supply Chain Platform</div><div class="itemDate">2022</div></div>
	</div>
	<div class="row"><!--
 --><div class="itemBar"><div class="itemInfo">Over 10,000 inverters delivered</div><div class="itemDate">2024.12</div></div><!--
 --><div class="itemBar"><div class="itemInfo">Company expanded to 3,600㎡ with 1 .2GW capacity</div><div class="itemDate">2024</div></div><!--
 --><div class="itemBar"><div class="itemInfo">Factory area expanded to 1,200㎡.</div><div class="itemDate">2023</div></div>
	</div>
 
</div>
</div>
<!-- Container (History) -->
 
 
 
 
 
 
 
<!-- Container (About Section) -->
<div id="about" class="container-fluid container-padding" hidden = true>
  <div class="row">
    <div class="col-sm-8">
      <h2>About Our Company</h2><br>
      <h4>Smarten Electric (SE) is an Battery Energy Storage System & Micro-grid Solution-making company.</h4>
<h4>We combine local knowledge with global expertise.</h4>
<h4>Contact our team to discuss how we might help you make your ESS and Microgrid.</h4>
 
    </div>
    <div class="col-sm-4">
      <img class="slideanim" src="/lib/exe/fetch.php/belize_container.jpg" width="500">
    </div>
  </div>
</div>
 
<div class="container-fluid container-padding bg-grey">
  <div class="row">
    <div class="col-sm-4">
      <img class="slideanim" src="/lib/exe/fetch.php/render2-g.png" alt="" width="600">
    </div>
    <div class="col-sm-8">
      <h2>Our Products</h2><br>
      <h4><strong>Focused in power electronics </strong> </h4>
      <h4>Our mission is to develop the best power electronics</h4>
    </div>
  </div>
</div>
 
 
 
 
 
 
<!-- Container (Product Feature Section) -->
<div id="services" class="container-fluid container-padding text-center">
  <h2>What make our products different</h2>
  <br>
  <div class="row slideanim">
    <div class="col-sm-4">
      <span class="glyphicon glyphicon-flash logo-small"></span>
      <h4>Generator orientated</h4>
      <p>Designed for collaborating with generators, optimizing fuel efficiency and peak shave impulse heavy loads</p>
    </div>
    <div class="col-sm-4">
      <span class="glyphicon glyphicon-heart logo-small"></span>
      <h4>Endurable</h4>
      <p>Dedicated for Micro-grid, enduring x1.5 overload for 30 seconds at most.
No derating until 45°C.
Wide AC voltage, no matter which continent you are standing on</p>
    </div>
    <div class="col-sm-4">
      <span class="glyphicon glyphicon-duplicate logo-small"></span>
      <h4>Parallel Operation</h4>
      <p>Capable to operate in parallel, either grid-tied or grid-forming mode</p>
    </div>
  </div>
  <br><br>
  <div class="row slideanim">
    <div class="col-sm-4">
      <span class="glyphicon glyphicon-flash logo-small"></span>
      <h4>SiC Tech</h4>
      <p>SiC MOSFETs empowered, making marvelous heat performance
</p>
    </div>
    <div class="col-sm-4">
      <span class="glyphicon glyphicon-certificate logo-small"></span>
      <h4>Easy to deploy</h4>
      <p>A library of many BMS protocols is built-in, mainstream lithrium ion battery brands are supported.</p>
    </div>
    <div class="col-sm-4">
      <span class="glyphicon glyphicon-tint logo-small"></span>
      <h4>Outdoor rated</h4>
      <p>IP65 rated, separated wind-route makes no air blowing the internal core components, almost maintenance-free, which will liberate you from precious workmanship cost.
The small foot print will save your precious space.</p>
    </div>
  </div>
</div>
 
 
<!-- Container (Scenarios Section) -->
<div id="scenarios" class="container-fluid container-padding">
  <div class="text-center">
    <h2>Application Scenarios</h2>
    <h4>Our solutions are capable for various scenarios</h4>
  </div>
  <div class="row slideanim">
    <div class="col-sm-4 col-xs-12">
      <div class="panel panel-default text-center">
        <div class="panel-heading">
          <h3>Off-grid Solutions</h3>
        </div>
        <div class="panel-body">
          <div class="thumbnail">
          <img src="/lib/exe/fetch.php/micro-grid.png" alt="factory" width="300" height="300">
          <p>A microgrid is a group of interconnected loads and distributed energy resources that acts as a single controllable entity with respect to the grid.</p>
           </div>
        </div>
        <div class="panel-footer">
          <h3></h3>
        </div>
      </div>      
    </div>     
    <div class="col-sm-4 col-xs-12">
      <div class="panel panel-default text-center">
        <div class="panel-heading">
          <h3>Weak Grid Solutions</h3>
        </div>
        <div class="panel-body">
         <div class="thumbnail">
          <img src="/lib/exe/fetch.php/moduel-in-mobile.png" alt="factory" width="300" height="300">
          <p>A mobile battery system like a battery trailer, can be transported easily to anywhere that needs clean energy</p>
          </div>
        </div>
        <div class="panel-footer">
          <h3></h3>
        </div>
      </div>      
    </div>  
    <div class="col-sm-4 col-xs-12">
      <div class="panel panel-default text-center">
        <div class="panel-heading">
          <h3>Grid-connected Solutions</h3>
        </div>
        <div class="panel-body">
         <div class="thumbnail">
          <img src="/lib/exe/fetch.php/grid-support.png" alt="factory" width="300" height="300">
          <p>Grid support means voltage control in the event of voltage dips/rises during subtransmission/transmission system faults to avoid an unintentional disconnection of large feed-in PV-DG power, and to maintain system stability</p>
         </div>
        </div>
        <div class="panel-footer">
          <h3></h3>
        </div>
      </div>      
    </div>    
  </div>
</div>
 
 
 
<!-- Container (Why us) -->
<div id="Why us" class="container-fluid container-padding text-center bg-grey">
  <h2>Why us</h2><br>
  <h3>We make your value in these features</h3>
        <div class="CardsContainer">
            <div class="CardContainer">
                <div class="CardInnerContainer">
                    <h3>Know-how</h3>
                    <h5>With 50% of employees who have engineer backgrounds, we are good on knowing how to design ESS and Micro-grid solution.</h5>
                    <div class="CardImageContainer">
                        <img src="/lib/exe/fetch.php/know-how.png">
                    </div>
                </div>
            </div>
            <div class="CardContainer">
                <div class="CardInnerContainer" >
                    <h3>Experience</h3>
                    <h5>We are a team with more than 7 years experience in ESS & micro-grid.</h5>
                    <div class="CardImageContainer">
                        <img src="/lib/exe/fetch.php/img_5318.jpg">
                    </div>
                </div>
            </div>
            <div class="CardContainer">
                <div class="CardInnerContainer" >
                    <h3>R&D and factory</h3>
                    <h5>We have our own R&D and our own factory, everything is fully controlled.</h5>
                    <div class="CardImageContainer">
                        <img src="/lib/exe/fetch.php/60d9ff3c9ba5b7cb4577a4f1a68ed210.jpg">
                    </div>
                </div>
            </div>
        </div>
</div>
 
 
<!-- Container (Contact Section) -->
<div id="contact" class="container-fluid container-padding" style = "background-color: rgba(246, 246, 246, 0.5);position: relative;z-index: -2;">
 
<div style = "position: absolute;top: 0;left: 0;width: 100%;height: 100%;z-index: -1;background-image: url('/lib/exe/fetch.php/f1111bfb-abf4-47a5-b50c-6336de9add99_1745477253284360892_origin_tplv-a9rns2rl98-image-dark-watermark.jpg');background-position: 0 25%;background-size: cover;background-repeat: no-repeat;  filter: blur(5px);-webkit-filter: blur(5px); "></div>
  <h2 class="text-center">Contact</h2>
  <div class="row">
    <div class="col-sm-5">
      <p>Contact us and we'll get back to you within 24 hours.</p>
      <p><span class="glyphicon glyphicon-map-marker"></span> 2nd Floor, Sogood Science Park, Sanwei Community, Hangcheng Street, Bao'an District, Shenzhen, Guangdong, 518000, PRC </p>
      <p><span class="glyphicon glyphicon-phone"></span> </p>
      <p><span class="glyphicon glyphicon-envelope"></span> info@smartenelectric.com</p>
 
 
 
    </div>
    <div class="col-sm-7 slideanim thumbnail" style="border-radius: 15px" >
     <!-- Image of location/map -->
<img src="../lib/exe/fetch.php/20250424220153.png" class="w3-image w3-greyscale-min" style="width:100%,border-radius: 15px" >
 
    </div>
  </div>
</div>
</div>
</div>
 
 
<footer class="container-fluid text-center">
  <p>Copyright 2025  Shenzhen Smarten Electric Co., Ltd. All Rights Reserved.</p>
</footer>
 
<script>
$(document).ready(function(){
  // Add smooth scrolling to all links in navbar + footer link
  $(".navbar a, footer a[href='#myPage']").on('click', function(event) {
    // Make sure this.hash has a value before overriding default behavior
    if (this.hash !== "") {
      // Prevent default anchor click behavior
      event.preventDefault();
 
      // Store hash
      var hash = this.hash;
 
      // Using jQuery's animate() method to add smooth page scroll
      // The optional number (900) specifies the number of milliseconds it takes to scroll to the specified area
      $('html, body').animate({
        scrollTop: $(hash).offset().top
      }, 900, function(){
 
        // Add hash (#) to URL when done scrolling (default click behavior)
        window.location.hash = hash;
      });
    } // End if
  });
 
  $(window).scroll(function() {
    $(".slideanim").each(function(){
      var pos = $(this).offset().top;
 
      var winTop = $(window).scrollTop();
        if (pos < winTop + 600) {
          $(this).addClass("slide");
        }
    });
  });
})
 
 
//wrapped panels
const cardsContainer = document.querySelectorAll('.CardsContainer');
 
const setUpTopCards = () => {
    for (let index = 0; index < cardsContainer.length; index++) {
        const cards = cardsContainer[index].querySelectorAll('.CardContainer');
        for (let index = 0; index < cards.length; index++) {
            const card = cards[index];
            card.style.top = (index + 1) * 10 + "px";
        }
    }
 
}
setUpTopCards();
 
window.addEventListener("scroll", () => {
    for (let index = 0; index < cardsContainer.length; index++) {
        const cards = cardsContainer[index].querySelectorAll('.CardContainer');
        var flag = true;
        if (flag) {
            flag = false;
            var data = {};
            data.Location = {};
            data.ToReduseBy = {};
            for (let index = 0; index < cards.length; index++) {
                const card = cards[index];
                const stickyTop = parseInt(window.getComputedStyle(card).top);
                const currentTop = card.getBoundingClientRect().top;
                data.Location[index] = currentTop - stickyTop;
                data.ToReduseBy[index] = 0;
            }
 
            for (let index = 0; index < cards.length; index++) {
                if (data.Location[index] <= 20) {
                    for (let j = index; j > -1; j--) {
                        data.ToReduseBy[j]++;
                    }
                }
            }
 
            for (let index = 0; index < cards.length; index++) {
                const card = cards[index];
                card.getElementsByClassName('CardInnerContainer')[0].style.transform = `scale(${1 - (data.ToReduseBy[index] * 0.05)})`;
            }
 
            setTimeout(() => {
                flag = true;
            }, 100)
        }
    }
});
 
 
 
 
 
</script>
<style>
 
#dokuwiki__pageheader{
display: none;
 
}
 
#dokuwiki__top {
  display: none;
}
 
 
 
 
 
body {
  padding: 0;
  margin: 0;
  font-family: 'Montserrat', sans-serif;
  font-weight: bold;
  margin-top: 200px;
}
 
.col-md-4 {
  text-align: center;
  padding-bottom: 50px;
  border-right: 1px dashed black;
}
 
.col-md-4:last-child {
  border-right: 0px solid black;
}
 
.counter {
  animation-duration: 1s;
  animation-delay: 0s;
}
 
i {
  font-size: 20px !Important;
}
 
@media (max-width: 991px) {
  .col-md-4 {
    border-right: 0px dashed black;
    border-bottom: 1px dashed black;
    width: 50%;
    margin: auto auto;
  }
 
  .col-md-4:last-child {
    border-bottom: 0px dashed black;
  }
}
 
 
 
 
 
 
 
.CardsContainer{
    height: max-content;
}
 
.CardContainer{
    position: sticky;
    display: flex;
    align-items: flex-start;
}
 
.CardInnerContainer{
    margin: auto;
    padding: 20px;
    box-shadow: 0 0 30px 0 rgba(0,0,0,1.0);
    width: calc(70% - 40px);
    transition: 0.3s;
    color: white;
    background-color: #b5deeae8;
    //backdrop-filter: blur(4px);
    transform-origin: top center;
    border-radius: 15px
}
 
.CardInnerContainer p{
    font-size: 20px;
}
 
.CardImageContainer{
    max-height: 100vh;
    overflow: hidden;
}
 
.CardImageContainer img{
    width: 100%;
    height: 100%;
    object-fit: contain;
}
 
 
 
.scroll-sequence__container.tree-container {
  width: 100vw;
  margin-left: calc(-50vw + 50%);
}
 
.scroll-container {
  //height: 100vh;
  background: rgba(0,0,0,0.6);
}
 
.speak {
  margin: 150vh 0;
  color: #00d9ff;
  font-size: 1.875em;
  text-shadow: 2px 0px 10px black;
}
 
.speak:first-child {
  margin-top: -50vh;
}
 
.speak[data-scroll] {
  transform: translatey(calc(var(--viewport-y) * 30vh));
  opacity: calc(var(--visible-y));
}
 
.scroll-sequence__content {
  padding: 4em;
}
 
.scroll-sequence {
  position: sticky;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  //z-index: -5;
  height: 100vh;
  background-position: center;
  background-size: cover;
  background-repeat: no-repeat;
}
 
 
body {
  margin: 0;
}
 
* {
  box-sizing: border-box;
}
 
 
 
 
 
 
.mapWrapper {
  position: relative;
  box-sizing: content-box !important;
  width: 90%;
  left: 50%;
  top: 0%;
  transform: translateX(-50%);
}
 
.mapWrapper:before,
.mapWrapper:after {
  box-sizing: content-box !important;
}
 
.mapWrapper .row {
  position: relative;
  width: 100%;
  left: 0;
  height: 10em;
}
.mapWrapper .row .itemBar {
  position: relative;
  display: inline-block;
  width: 33.3333333333%;
  height: 0.25em;
  margin-top: 6.875em;
  background: rgba(93, 132, 187, 0.5);
}
.mapWrapper .row .itemBar .itemInfo {
  position: absolute;
  width: 100%;
  bottom: 0.5em;
  text-align: center;
}
.mapWrapper .row .itemBar .itemInfo:after {
box-sizing: content-box !important;
  content: "";
  position: absolute;
  width: 0.5em;
  height: 0.25em;
  background: rgba(93, 132, 187, 0.5);
  border-radius: 3em 3em 0 0;
  left: 50%;
  transform: translateX(-50%);
  bottom: -0.25em;
  transition: width 0.2s ease-in, height 0.2s ease-in;
}
.mapWrapper .row .itemBar:hover .itemInfo:after {
box-sizing: content-box !important;
  width: 2.5em;
  height: 0.25em;
  transition: width 0.2s ease-in, height 0.2s ease-in;
}
.mapWrapper .row .itemBar .itemDate {
  position: absolute;
  width: 100%;
  font-size: 2em;
  top: 0.25em;
  text-align: center;
  color: #19adb2;
  //text-shadow: 1px 1px 2px black;
}
.mapWrapper .row:nth-child(2n) .itemBar:first-child:after {
box-sizing: content-box !important;
  content: "";
  position: absolute;
  width: 1.75em;
  height: 9.75em;
  right: 100%;
  top: 0;
  border-radius: 7em 0 0 7em;
  border: 0.25em solid rgba(93, 132, 187, 0.5);
  border-right: unset;
}
.mapWrapper .row:nth-child(2n+1) .itemBar:last-child:after {
box-sizing: content-box !important;
  content: "";
  position: absolute;
  width: 1.75em;
  height: 9.75em;
  left: 100%;
  top: 0;
  border-radius: 0 7em 7em 0;
  border: 0.25em solid rgba(93, 132, 187, 0.5);
  border-left: unset;
}
.mapWrapper .row:last-child .itemBar:after {
box-sizing: content-box !important;
  display: none;
}
 
 
 
 
 
 
 
 
 
 
</style>
 
 
<script src='https://unpkg.com/scroll-out@2.2.3/dist/scroll-out.min.js'></script>
 
<script>
const treeSequenceImages = [];
for (let i = 1; i <= 60; i ++) {
  treeSequenceImages.push(`${`0000${i}`.slice(-4)}.jpg`);
}
 
//document.getElementById("sequence-container-1").style.height = `${11*(treeSequenceImages.length+1)}vh`;
const requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
 
class EventEmitter {
  listeners = {}
  addListener(eventName, fn) {
    this.listeners[eventName] = this.listeners[eventName] || [];
    this.listeners[eventName].push(fn);
    return this;
  }
  on(eventName, fn) {
    return this.addListener(eventName, fn);
  }
  once(eventName, fn) {
    this.listeners[eventName] = this.listeners[eventName] || [];
    const onceWrapper = () => {
      fn();
      this.off(eventName, onceWrapper);
    }
    this.listeners[eventName].push(onceWrapper);
    return this;
  }
  off(eventName, fn) {
    return this.removeListener(eventName, fn);
  }
  removeListener (eventName, fn) {
    let lis = this.listeners[eventName];
    if (!lis) return this;
    for(let i = lis.length; i > 0; i--) {
      if (lis[i] === fn) {
        lis.splice(i,1);
        break;
      }
    }
    return this;
  }
  emit(eventName, ...args) {
    let fns = this.listeners[eventName];
    if (!fns) return false;
    fns.forEach((f) => {
      f(...args);
    });
    return true;
  }
  listenerCount(eventName) {
    let fns = this.listeners[eventName] || [];
    return fns.length;
  }
  rawListeners(eventName) {
    return this.listeners[eventName];
  }
}
class Canvas {
  constructor(e) {
    this.images = e.images;
    this.container = e.container;
    this.cover = e.cover;
    this.displayIndex = 0;
  }
 
  setup() {
    this.canvas = document.createElement("canvas");
    this.container.appendChild(this.canvas);
    this.ctx = this.canvas.getContext('2d')
 
    window.addEventListener('resize', () => this.resize());
    this.resize();
  }
 
  renderIndex(e) {
    if (this.images[e]) {
        return this.drawImage(e);
    }
    // Find closest loaded image
    for (var t = Number.MAX_SAFE_INTEGER, r = e; r >= 0; r--)
        if (this.images[r]) {
            t = r;
            break
        }
    for (var n = Number.MAX_SAFE_INTEGER, i = e, o = this.images.length; i < o; i++)
        if (this.images[i]) {
            n = i;
            break
        }
    this.images[t] ? this.drawImage(t) : this.images[n] && this.drawImage(n)
  }
 
  drawImage(e) {
    this.displayIndex = e,
    this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
    const x = Math.floor((this.canvas.width - this.images[this.displayIndex].naturalWidth) / 2);
    const y = Math.floor((this.canvas.height - this.images[this.displayIndex].naturalHeight) / 2);
    if (this.cover) {
 
      this.drawImageCover(this.ctx, this.images[this.displayIndex]);
    } else {
      this.ctx.drawImage(this.images[this.displayIndex], x, y);
    }
  }
 
  resize() {
    const w = this.container.clientWidth;
    const h = this.container.clientHeight;
    this.canvas.style.height = `${h}px`;
    this.canvas.style.width = `${w}px`;
    this.canvas.height = h;
    this.canvas.width = w;
 
    this.renderIndex(this.displayIndex);
  }
 
  /**
 * By Ken Fyrstenberg Nilsen
 *
 * drawImageProp(context, image [, x, y, width, height [,offsetX, offsetY]])
 *
 * If image and context are only arguments rectangle will equal canvas
*/
  drawImageCover(ctx, img, x, y, w, h, offsetX, offsetY) {
 
      if (arguments.length === 2) {
          x = y = 0;
          w = ctx.canvas.width;
          h = ctx.canvas.height;
      }
 
      // default offset is center
      offsetX = typeof offsetX === "number" ? offsetX : 0.5;
      offsetY = typeof offsetY === "number" ? offsetY : 0.5;
 
      // keep bounds [0.0, 1.0]
      if (offsetX < 0) offsetX = 0;
      if (offsetY < 0) offsetY = 0;
      if (offsetX > 1) offsetX = 1;
      if (offsetY > 1) offsetY = 1;
 
      var iw = img.width,
          ih = img.height,
          r = Math.min(w / iw, h / ih),
          nw = iw * r,   // new prop. width
          nh = ih * r,   // new prop. height
          cx, cy, cw, ch, ar = 1;
 
      // decide which gap to fill    
      if (nw < w) ar = w / nw;                             
      if (Math.abs(ar - 1) < 1e-14 && nh < h) ar = h / nh;  // updated
      nw *= ar;
      nh *= ar;
 
      // calc source rectangle
      cw = iw / (nw / w);
      ch = ih / (nh / h);
 
      cx = (iw - cw) * offsetX;
      cy = (ih - ch) * offsetY;
 
      // make sure source rectangle is valid
      if (cx < 0) cx = 0;
      if (cy < 0) cy = 0;
      if (cw > iw) cw = iw;
      if (ch > ih) ch = ih;
 
      // fill image in dest. rectangle
      ctx.drawImage(img, cx, cy, cw, ch,  x, y, w, h);
  }
}
class ImgLoader extends EventEmitter {
  constructor(opts) {
    super();
    this.images = opts.imgsRef;
    this.imageNames = opts.images;
    this.imagesRoot = opts.imagesRoot;
    this.sequenceLength = opts.images.length;
    this.priorityFranes = opts.priorityFrames;
    this.complete = false;
    this.loadIndex = 0;
 
    this.priorityQueue = this.createPriorityQueue();
    this.loadingQueue = this.createLoadingQueue();
 
    this.loadNextImage();
  }
 
  loadImage(e) {
    if (this.images[e]) {
      return this.loadNextImage();
    }
    const onLoad = () => {
      img.removeEventListener('load', onLoad);
      this.images[e] = img;
 
      if (e === 0) {
        this.emit('FIRST_IMAGE_LOADED');
      }
      this.loadNextImage();
    }
    const img = new Image;
    img.addEventListener('load', onLoad);
    img.src = (this.imagesRoot ? this.imagesRoot : '') + this.imageNames[e];
  }
 
  loadNextImage() {
    if (this.priorityQueue.length) {
      this.loadImage(this.priorityQueue.shift());
      if (!this.priorityQueue.length) {
        this.emit('PRIORITY_IMAGES_LOADED');
      }
    } else if (this.loadingQueue.length) {
        this.loadImage(this.loadingQueue.shift())
    } else {
      this.complete = true;
      this.emit('IMAGES_LOADED');
    }
  }
 
  createPriorityQueue() {
    const p = this.priorityFrames || [];
    if (!p.length) {
      p.push(0);
      p.push(Math.round(this.sequenceLength / 2));
      p.push(this.sequenceLength - 1);
    }
    return p;
  }
 
  createLoadingQueue() {
    return this.imageNames.map((s, i) => i).sort((e, n) => {
       return Math.abs(e - this.sequenceLength / 2) - Math.abs(n - this.sequenceLength / 2)
    });
  }
}
class ScrollSequence {
  constructor(opts) {
    this.opts = {
      container: 'body',
      starts: 'out',
      ends: 'out',
      imagesRoot: '',
      cover: false,
      ...opts
    }
    this.container = typeof opts.container === 'object' ? 
      opts.container : 
      document.querySelector(opts.container);
 
    this.scrollWith = !opts.scrollWith ? 
      this.container : 
      typeof opts.scrollWith === 'object' ? 
        opts.scrollWith : 
        document.querySelector(opts.scrollWith);
 
    this.images = Array(opts.images.length);
    this.imagesToLoad = opts.images;
    this.priorityFrames = opts.priorityFrames;
 
    this.loader = new ImgLoader({
      imgsRef: this.images,
      images: this.imagesToLoad,
      imagesRoot: this.opts.imagesRoot,
      priorityFrames: this.priorityFrames
    });
 
    this.canvas = new Canvas({
      container: this.container,
      images: this.images,
      cover: this.opts.cover
    });
 
    this.init();
  }
 
  init() {
    this.canvas.setup();
    this.loader.once('FIRST_IMAGE_LOADED', () => {
      this.canvas.renderIndex(0);
    })
    this.loader.once('PRIORITY_IMAGES_LOADED', () => {
      window.addEventListener('scroll', () => this.changeOnWindowScroll());
    })
    this.loader.once('IMAGES_LOADED', () => {
      console.log('Sequence Loaded');
    })
  }
 
  changeOnWindowScroll() {
    const step = 100 / (this.images.length - 1);
    const mapToIndex = Math.floor(this.percentScrolled / step);
    requestAnimationFrame(() => this.canvas.renderIndex(mapToIndex));
  }
 
  get percentScrolled() {
    const {starts, ends} = this.opts;
    const el = this.scrollWith;
    const doc = document.documentElement;
    const clientOffsety = doc.scrollTop || window.pageYOffset;
    const elementHeight = el.clientHeight || el.offsetHeight;
    const clientHeight = doc.clientHeight;
    let target = el;
    let offsetY = 0;
    do {
        offsetY += target.offsetTop;
        target = target.offsetParent;
    } while (target && target !== window);
 
    let u = (clientOffsety - offsetY);
    let d = (elementHeight + clientHeight)
 
    if (starts === 'out') u += clientHeight;
    if (ends === 'in') d -= clientHeight;
    if (starts == 'in') d -= clientHeight;
    // start: out, ends: out
    // const value = ((clientOffsety + clientHeight) - offsetY) / (clientHeight + elementHeight) * 100;
 
    //start: in, ends: out
    // const value = (clientOffsety - offsetY) / (elementHeight) * 100;
 
    //start: out, ends: in
    // const value = ((clientOffsety + clientHeight) - offsetY) / (elementHeight) * 100;
 
    // Start: in, ends: in
    // (clientOffsety - offsetY) / (elementHeight - clientHeight)
 
    const value = u / d * 100;
    return value > 100 ? 100 : value < 0 ? 0 : value;
  }
}
 
 
const treeSequence = new ScrollSequence({
  container: '.tree-sequence',
  scrollWith: '.tree-container',
  images: treeSequenceImages,
  //imagesRoot: 'https://jacobbelanger.com/assets/sequence/',
  imagesRoot: '/lib/exe/fetch.php/imagesequence:',
  priorityFrames: [0, 20, 40, 60, 90],
  cover: true,
  starts: 'out',
  ends: 'in'
});
 
// END SCROLL_SEQUENCE CODE
 
ScrollOut({
  targets: '.speak',
  cssProps: {
    viewportY: true,
    visibleY: true
  }
});
</script>