Have problem with animation

Hi there,

so i try to make an 3D Viewer for Models.
I used this nice tutorial for my project:

https://tympanus.net/codrops/2019/09/17/how-to-build-a-color-customizer-app-for-a-3d-model-with-three-js/

I changed and added some things but its almost still the same code. The only difference is, than the script is more dynamic and gets the values from a database.

So in the “normal” version you can select parts and use the swatches to change the color of a part. This works fine. But some models have animations so i tried to add THREE.AnimationMixer to the code.

Here is the code:

var alphaBetString = "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z";var alphaBetTable = alphaBetString.split(" ");var rot13String = "N O P Q R S T U V W X Y Z A B C D E F G H I J K L M n o p q r s t u v w x y z a b c d e f g h i j k l m";var rot13Table = rot13String.split(" ");var numberString = "1 2 3 4 5 6 7 8 9 0";var numberTable = numberString.split(" ");var rot5String = "6 7 8 9 0 1 2 3 4 5";var rot5Table = rot5String.split(" ");var symbolString = "~ ` ! @ # $ % ^ & * ( ) _ + - = { } [ ] \\ | ; \' : \" < > ? , . /";var symbolTable = symbolString.split(" ");

const LOADER = document.getElementById('js-loader');
const TRAY = document.getElementById('js-tray-slide');
const DRAG_NOTICE = document.getElementById('js-drag-notice');
var theModel;

var userip = document.getElementById('userip').value;
var username = document.getElementById('username').value;
var path = document.getElementById('path').value;
var size = document.getElementById('size').value;
var parts = document.getElementById('parts').value;
var colores = document.getElementById('colores').value;
var posX = document.getElementById('posX').value;
var posY = document.getElementById('posY').value;
var posZ = document.getElementById('posZ').value;
var rotaX = document.getElementById('rotaX').value;
var rotaY = document.getElementById('rotaY').value;
var rotaZ = document.getElementById('rotaZ').value;
var cameradistance = document.getElementById('cameradistance').value;

//var posX = document.getElementById('TESTANIMATION').value;
const clock = new THREE.Clock();

COLOR_ARRAY = colores.split(",");

var cnumber = document.getElementById('cnumber').value;

path = path.replace(userip,'');
path = path.replace(username,'');

var modelselect = document.getElementById('modelselect').value;

modelselect = modelselect.replace(userip,'');
modelselect = modelselect.replace(username,'');

const MODEL_PATH = "../" + path + "/" + rot13rot5Encode(modelselect) + ".glb";

var activeOption = 'part-001';
var loaded = false;

const BACKGROUND_COLOR = 0xf1f1f1;
// Init the scene
const scene = new THREE.Scene();
// Set background
scene.background = new THREE.Color(BACKGROUND_COLOR);
scene.fog = new THREE.Fog(BACKGROUND_COLOR, 20, 100);

const canvas = document.querySelector('#c'+ cnumber);

// Init the renderer
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true });

renderer.shadowMap.enabled = true;
renderer.setPixelRatio(window.devicePixelRatio);

var cameraFar = 5; // 5 Default

if(cameradistance)
{
	cameraFar = cameradistance;
}

document.body.appendChild(renderer.domElement);

// Add a camerra
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = cameraFar;
camera.position.x = 0;
camera.position.y = 0;

const INITIAL_MAP = []; for (let i=0; i < parts;i++)
	
	INITIAL_MAP.push({
    childID: `part-${String(i+1).padStart(3, '0')}`, // padding the number
    mtl: new THREE.MeshPhongMaterial({ color: parseInt(COLOR_ARRAY[i]), shininess: 10 })
  })  
 

// Init the object loader
var loader = new THREE.GLTFLoader();

loader.load(MODEL_PATH, function (gltf) {
  theModel = gltf.scene; 

  theModel.traverse(o => {
    if (o.isMesh) {
      o.castShadow = true;
      o.receiveShadow = true;
    }
  });

  // Set the models initial scale   
  theModel.scale.set(size, size, size);
  
  //Use if model is wrong way turned
  if(rotaX != 0)
  {
	 theModel.rotation.x = rotaX;
  }
  
  if(rotaY != 0)
  {
	 theModel.rotation.y = rotaY;
  }
  
  if(rotaZ != 0)
  {
	 theModel.rotation.z = rotaZ;
  }

  // Offset the position a bit
  
  if(posX != 0)
  {
	 theModel.position.x = posX; 
  }
  
  if(posY != 0)
  {
	 theModel.position.y = posY; 
  }
  else
  {
	  theModel.position.y = -1;
  }
  
  if(posZ != 0)
  {
	 theModel.position.z = posZ; 
  }

  // Set initial textures
  for (let object of INITIAL_MAP) {
    initColor(theModel, object.childID, object.mtl);
  }

  // Add the model to the scene
  scene.add(theModel);
  
  // Remove the loader  
  LOADER.remove();
  
  mixer = new THREE.AnimationMixer( theModel );
  mixer.clipAction( gltf.animations[ 0 ] ).play();  

}, undefined, function (error) {
  console.error(error);
});

// Function - Add the textures to the models
function initColor(parent, type, mtl) {
  parent.traverse(o => {
    if (o.isMesh) {
      if (o.name.includes(type)) {
        o.material = mtl;
        o.nameID = type; // Set a new property to identify this object
      }
    }
  });
}

pointLight = new THREE.PointLight( 0xffffff, 0.33 );
pointLight.position.set(0,1,2);
camera.add(pointLight);
scene.add( camera );

// Add lights
var hemiLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.61);
hemiLight.position.set(0, 50, 0);
// Add hemisphere light to scene   
scene.add(hemiLight);

var dirLight = new THREE.DirectionalLight(0xffffff, 0.54);
dirLight.position.set(-8, 12, 8);
dirLight.castShadow = true;
dirLight.shadow.mapSize = new THREE.Vector2(1024 * 4, 1024 * 4);
// Add directional Light to scene    
scene.add(dirLight);

// Floor
var floorGeometry = new THREE.PlaneGeometry(5000, 5000, 1, 1);
var floorMaterial = new THREE.MeshPhongMaterial({
  color: 0xeeeeee,
  shininess: 0 });


var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.rotation.x = -0.5 * Math.PI;
floor.receiveShadow = true;
floor.position.y = -1;
scene.add(floor); 

// Add controls
var controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.maxPolarAngle = 360;
controls.minPolarAngle = 0;
controls.enableDamping = true;
controls.enablePan = false;
controls.dampingFactor = 0.1;
controls.autoRotate = false; // Toggle this if you'd like the chair to automatically rotate
controls.autoRotateSpeed = 15.5; // 30

function animate() {

  const delta = clock.getDelta();
  requestAnimationFrame(animate);  
  controls.update();  
  //mixer.update( delta );  
  renderer.render(scene, camera);  

  if (resizeRendererToDisplaySize(renderer)) {
    const canvas = renderer.domElement;
    camera.aspect = canvas.clientWidth / canvas.clientHeight;	
    camera.updateProjectionMatrix();	
  }  

  if (theModel != null && loaded == false) {
	initialRotation();
    DRAG_NOTICE.classList.add('start');
  }  
}

animate();

// Function - New resizing method
function resizeRendererToDisplaySize(renderer) {
  const canvas = renderer.domElement;
  var width = window.innerWidth;
  var height = window.innerHeight;
  var canvasPixelWidth = canvas.width / window.devicePixelRatio;
  var canvasPixelHeight = canvas.height / window.devicePixelRatio;

  const needResize = canvasPixelWidth !== width || canvasPixelHeight !== height;
  if (needResize) {

    renderer.setSize(width, height, false);
  }
  return needResize;
}

// Function - Build Colors

function buildColors(colors) {
  for (let [i, color] of colors.entries()) {
    let swatch = document.createElement('div');
    swatch.classList.add('tray__swatch');

    if (color.texture)
    {
      swatch.style.backgroundImage = "url(" + color.texture + ")";
    } else
    {
      swatch.style.background = "#" + color.color;
    }

    swatch.setAttribute('data-key', i);
    TRAY.append(swatch);
  }
}

buildColors(colors);

// Select Option
const options = document.querySelectorAll(".option");

for (const option of options) {
  option.addEventListener('click', selectOption);
}

function selectOption(e) {
  let option = e.target;
  activeOption = e.target.dataset.option;
  for (const otherOption of options) {
    otherOption.classList.remove('--is-active');
  }
  option.classList.add('--is-active');
}

// Swatches
const swatches = document.querySelectorAll(".tray__swatch");

for (const swatch of swatches) {
  swatch.addEventListener('click', selectSwatch);
}

function selectSwatch(e) {
  let color = colors[parseInt(e.target.dataset.key)];
  let new_mtl;

  if (color.texture) {

    let txt = new THREE.TextureLoader().load(color.texture);

    txt.repeat.set(color.size[0], color.size[1], color.size[2]);
    txt.wrapS = THREE.RepeatWrapping;
    txt.wrapT = THREE.RepeatWrapping;

    new_mtl = new THREE.MeshPhongMaterial({
      map: txt,
      shininess: color.shininess ? color.shininess : 10 });

  } else

  {
    new_mtl = new THREE.MeshPhongMaterial({
      color: parseInt('0x' + color.color),
      shininess: color.shininess ? color.shininess : 10 });


  }

  setMaterial(theModel, activeOption, new_mtl);
}

function setMaterial(parent, type, mtl) {
  parent.traverse(o => {
    if (o.isMesh && o.nameID != null) {
      if (o.nameID == type) {
        o.material = mtl;
      }
    }
  });
}

// Function - Opening rotate
let initRotate = 0;

function initialRotation() {
  initRotate++;
  if (initRotate <= 120) {
    theModel.rotation.y += Math.PI / 60;
  } else {
    loaded = true;
  }
}

var slider = document.getElementById('js-tray'),sliderItems = document.getElementById('js-tray-slide'),difference;

function slide(wrapper, items) {
  var posX1 = 0,
  posX2 = 0,
  posInitial,
  threshold = 20,
  posFinal,
  slides = items.getElementsByClassName('tray__swatch');

  // Mouse events
  items.onmousedown = dragStart;

  // Touch events
  items.addEventListener('touchstart', dragStart);
  items.addEventListener('touchend', dragEnd);
  items.addEventListener('touchmove', dragAction);


  function dragStart(e) {
    e = e || window.event;
    posInitial = items.offsetLeft;
    difference = sliderItems.offsetWidth - slider.offsetWidth;
    difference = difference * -1;

    if (e.type == 'touchstart') {
      posX1 = e.touches[0].clientX;
    } else {
      posX1 = e.clientX;
      document.onmouseup = dragEnd;
      document.onmousemove = dragAction;
    }
  }

  function dragAction(e) {
    e = e || window.event;

    if (e.type == 'touchmove') {
      posX2 = posX1 - e.touches[0].clientX;
      posX1 = e.touches[0].clientX;
    } else {
      posX2 = posX1 - e.clientX;
      posX1 = e.clientX;
    }

    if (items.offsetLeft - posX2 <= 0 && items.offsetLeft - posX2 >= difference) {
      items.style.left = items.offsetLeft - posX2 + "px";
    }
  }

  function dragEnd(e) {
    posFinal = items.offsetLeft;
    if (posFinal - posInitial < -threshold) {

    } else if (posFinal - posInitial > threshold) {

    } else {
      items.style.left = posInitial + "px";
    }

    document.onmouseup = null;
    document.onmousemove = null;
  }

}

function rot13rot5Encode(input) {    var output = "";    for (var i=0; i<input.length; i++) {         for (var y=0; y<numberTable.length; y++) {            if (input[i]==numberTable[y]) {                output+=rot5Table[y];            }        }        for (var x=0; x<alphaBetTable.length; x++) {            if (input[i]==alphaBetTable[x]) {                output+=rot13Table[x];            }        }        for (var w=0; w<symbolTable.length; w++) {            if (input[i]==symbolTable[w]) {                output+=symbolTable[w];            }        }        if (input[i]==" ") {            output+=" ";        }    }    return output;};

slide(slider, sliderItems);

When i add mixer.update( delta ); at line 209 i can’t use the swatches anymore and the info “Drag to rotate 360°” don’t disappear. But the animation works this way. It seems that mixer.update( delta ); blocks the rest of the code…

Normal:

With animation:

Can someone help me please.

Anybody ? When i find a fix for my problem i will post it here.

I think that the order of my code is wrong or some condition is at the wrong place, so AnimationMixer is in a loop and the rest of the code is ignored/blocked.

So i was right. The order was wrong and i needed to check if model is loaded.

Here is my working code:

var alphaBetString = "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z";var alphaBetTable = alphaBetString.split(" ");var rot13String = "N O P Q R S T U V W X Y Z A B C D E F G H I J K L M n o p q r s t u v w x y z a b c d e f g h i j k l m";var rot13Table = rot13String.split(" ");var numberString = "1 2 3 4 5 6 7 8 9 0";var numberTable = numberString.split(" ");var rot5String = "6 7 8 9 0 1 2 3 4 5";var rot5Table = rot5String.split(" ");var symbolString = "~ ` ! @ # $ % ^ & * ( ) _ + - = { } [ ] \\ | ; \' : \" < > ? , . /";var symbolTable = symbolString.split(" ");

const LOADER = document.getElementById('js-loader');
const TRAY = document.getElementById('js-tray-slide');
const DRAG_NOTICE = document.getElementById('js-drag-notice');
var theModel;

var userip = document.getElementById('userip').value;
var username = document.getElementById('username').value;
var path = document.getElementById('path').value;
var size = document.getElementById('size').value;
var parts = document.getElementById('parts').value;
var colores = document.getElementById('colores').value;
var posX = document.getElementById('posX').value;
var posY = document.getElementById('posY').value;
var posZ = document.getElementById('posZ').value;
var rotaX = document.getElementById('rotaX').value;
var rotaY = document.getElementById('rotaY').value;
var rotaZ = document.getElementById('rotaZ').value;
var cameradistance = document.getElementById('cameradistance').value;
var lightintensity = document.getElementById('lightintensity').value;
let mixer;

//var posX = document.getElementById('TESTANIMATION').value;
const clock = new THREE.Clock();

COLOR_ARRAY = colores.split(",");

var cnumber = document.getElementById('cnumber').value;

path = path.replace(userip,'');
path = path.replace(username,'');

var modelselect = document.getElementById('modelselect').value;

modelselect = modelselect.replace(userip,'');
modelselect = modelselect.replace(username,'');

const MODEL_PATH = "../" + path + "/" + rot13rot5Encode(modelselect) + ".glb";
const MODEL_MAN = "../img/man.glb";

var activeOption = 'part-001';
var loaded = false;

const BACKGROUND_COLOR = 0xf1f1f1;
// Init the scene
const scene = new THREE.Scene();
// Set background
scene.background = new THREE.Color(BACKGROUND_COLOR);
scene.fog = new THREE.Fog(BACKGROUND_COLOR, 20, 100);

const canvas = document.querySelector('#c'+ cnumber);

// Init the renderer
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true });

renderer.shadowMap.enabled = true;
renderer.setPixelRatio(window.devicePixelRatio);

var cameraFar = 5; // 5 Default

if(cameradistance)
{
	cameraFar = cameradistance;
}

document.body.appendChild(renderer.domElement);

// Add a camerra
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = cameraFar;
camera.position.x = 0;
camera.position.y = 0;

	const INITIAL_MAP = []; for (let i=0; i < parts;i++)
	
	INITIAL_MAP.push({
    childID: `part-${String(i+1).padStart(3, '0')}`, // padding the number
    mtl: new THREE.MeshPhongMaterial({ color: parseInt(COLOR_ARRAY[i]), shininess: 10 })
  }) 

// Init the object loader
var loader = new THREE.GLTFLoader();

/*loader.load(MODEL_MAN, function (gltf) {
  theMan = gltf.scene; 

  theMan.traverse(o => {
    if (o.isMesh) {
      o.castShadow = true;
      o.receiveShadow = true;
    }
  });

  // Set the models initial scale   
  theMan.scale.set(size, size, size);
  
  //Use if model is wrong way turned  
  
	theMan.rotation.x = 0;
	theMan.rotation.y = 80;
	theMan.rotation.z = 0;
	
	theMan.position.x = 2; 
	theMan.position.y = -1.05; 
	theMan.position.z = 0;	

  // Add the model to the scene
  scene.add(theMan);
  
  // Remove the loader  
  LOADER.remove();  

}, undefined, function (error) {
  console.error(error);
});

*/

loader.load(MODEL_PATH, function (gltf) {
  theModel = gltf.scene; 

  theModel.traverse(o => {
    if (o.isMesh) {
      o.castShadow = true;
      o.receiveShadow = true;
    }
  });

  // Set the models initial scale   
  theModel.scale.set(size, size, size);
  
  //Use if model is wrong way turned
  if(rotaX != 0)
  {
	 theModel.rotation.x = rotaX;
  }
  
  if(rotaY != 0)
  {
	 theModel.rotation.y = rotaY;
  }
  
  if(rotaZ != 0)
  {
	 theModel.rotation.z = rotaZ;
  }

  // Offset the position a bit
  
  if(posX != 0)
  {
	 theModel.position.x = posX; 
  }
  
  if(posY != 0)
  {
	 theModel.position.y = posY; 
  }
  
  if(posZ != 0)
  {
	 theModel.position.z = posZ; 
  }

  // Set initial textures
  for (let object of INITIAL_MAP) {
    initColor(theModel, object.childID, object.mtl);
  }

  // Add the model to the scene
  scene.add(theModel);
  
  // Remove the loader  
  LOADER.remove();
  
  mixer = new THREE.AnimationMixer( theModel );
  mixer.clipAction( gltf.animations[ 0 ] ).play();

  

}, undefined, function (error) {
  console.error(error);
});

// Function - Add the textures to the models
function initColor(parent, type, mtl) {
  parent.traverse(o => {
    if (o.isMesh) {
      if (o.name.includes(type)) {
        o.material = mtl;
        o.nameID = type; // Set a new property to identify this object
      }
    }
  });
}

// Add lights
var pointLight = new THREE.PointLight( 0xffffff, 0.3 );
pointLight.position.set(0,1,2);
camera.add(pointLight);
scene.add( camera );

var hemiLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.3);
hemiLight.position.set(0, 50, 0);   
scene.add(hemiLight);

var dirLight = new THREE.DirectionalLight(0xffffff, 1);
dirLight.position.set(-8, 12, 8);
dirLight.castShadow = true;
dirLight.shadow.mapSize = new THREE.Vector2(1024 * 4, 1024 * 4);   
scene.add(dirLight);

// -x right
const light1 = new THREE.DirectionalLight( 0xffffff, lightintensity );
light1.position.set( - 16.116, 14.37, 8.208 );
light1.scale.set( 0.1, 2.428, 2.739 );
scene.add( light1 );

// -x left
const light2 = new THREE.DirectionalLight( 0xffffff, lightintensity );
light2.position.set( - 16.109, 18.021, - 8.207 );
light2.scale.set( 0.1, 2.425, 2.751 );
scene.add( light2 );

// +x
const light3 = new THREE.DirectionalLight( 0xffffff, lightintensity );
light3.position.set( 14.904, 12.198, - 1.832 );
light3.scale.set( 0.15, 4.265, 6.331 );
scene.add( light3 );

// +z
const light4 = new THREE.DirectionalLight( 0xffffff, lightintensity );
light4.position.set( - 0.462, 8.89, 14.520 );
light4.scale.set( 4.38, 5.441, 0.088 );
scene.add( light4 );

// -z
const light5 = new THREE.DirectionalLight( 0xffffff, lightintensity );
light5.position.set( 3.235, 11.486, - 12.541 );
light5.scale.set( 2.5, 2.0, 0.1 );
scene.add( light5 );

// +y
const light6 = new THREE.DirectionalLight( 0xffffff, lightintensity );
light6.position.set( 0.0, 20.0, 0.0 );
light6.scale.set( 1.0, 0.1, 1.0 );
scene.add( light6 );

// Floor
var floorGeometry = new THREE.PlaneGeometry(5000, 5000, 1, 1);
var floorMaterial = new THREE.MeshPhongMaterial({
  color: 0xeeeeee,
  shininess: 0 });


var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.rotation.x = -0.5 * Math.PI;
floor.receiveShadow = true;
floor.position.y = -1;
scene.add(floor); 

// Add controls
var controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.maxPolarAngle = 360;
controls.minPolarAngle = 0;
controls.enableDamping = true;
controls.enablePan = false;
controls.dampingFactor = 0.1;
controls.autoRotate = false; 
controls.autoRotateSpeed = 15.5; // 30

function animate() {

  const delta = clock.getDelta();  
  requestAnimationFrame(animate); 
  controls.update();

  renderer.render(scene, camera);  

  if (resizeRendererToDisplaySize(renderer)) {
    const canvas = renderer.domElement;
    camera.aspect = canvas.clientWidth / canvas.clientHeight;	
    camera.updateProjectionMatrix();	
  }  

  if (theModel != null && loaded == false) {
	initialRotation();	 
    DRAG_NOTICE.classList.add('start');       	 
  }
  
  if (theModel != null && loaded == true) {
    //Mixer at wrong position - blocks the start swatch and co.
    mixer.update( delta );
  }
}

animate();

// Function - New resizing method
function resizeRendererToDisplaySize(renderer) {
  const canvas = renderer.domElement;
  var width = window.innerWidth;
  var height = window.innerHeight;
  var canvasPixelWidth = canvas.width / window.devicePixelRatio;
  var canvasPixelHeight = canvas.height / window.devicePixelRatio;

  const needResize = canvasPixelWidth !== width || canvasPixelHeight !== height;
  if (needResize) {

    renderer.setSize(width, height, false);
  }
  return needResize;
}

// Function - Build Colors

function buildColors(colors) {
  for (let [i, color] of colors.entries()) {
    let swatch = document.createElement('div');
    swatch.classList.add('tray__swatch');

    if (color.texture)
    {
      swatch.style.backgroundImage = "url(" + color.texture + ")";
    } else
    {
      swatch.style.background = "#" + color.color;
    }

    swatch.setAttribute('data-key', i);
    TRAY.append(swatch);
  }
}

if(parts > 0)
{
	buildColors(colors);
}

// Select Option
const options = document.querySelectorAll(".option");

for (const option of options) {
  option.addEventListener('click', selectOption);
}

function selectOption(e) {
  let option = e.target;
  activeOption = e.target.dataset.option;
  for (const otherOption of options) {
    otherOption.classList.remove('--is-active');
  }
  option.classList.add('--is-active');
}

// Swatches
const swatches = document.querySelectorAll(".tray__swatch");

for (const swatch of swatches) {
  swatch.addEventListener('click', selectSwatch);
}

function selectSwatch(e) {
  let color = colors[parseInt(e.target.dataset.key)];
  let new_mtl;

  if (color.texture) {

    let txt = new THREE.TextureLoader().load(color.texture);

    txt.repeat.set(color.size[0], color.size[1], color.size[2]);
    txt.wrapS = THREE.RepeatWrapping;
    txt.wrapT = THREE.RepeatWrapping;

    new_mtl = new THREE.MeshPhongMaterial({
      map: txt,
      shininess: color.shininess ? color.shininess : 10 });

  } else

  {
    new_mtl = new THREE.MeshPhongMaterial({
      color: parseInt('0x' + color.color),
      shininess: color.shininess ? color.shininess : 10 });


  }

  setMaterial(theModel, activeOption, new_mtl);
}

function setMaterial(parent, type, mtl) {
  parent.traverse(o => {
    if (o.isMesh && o.nameID != null) {
      if (o.nameID == type) {
        o.material = mtl;
      }
    }
  });
}

// Function - Opening rotate
let initRotate = 0;

function initialRotation() {
  initRotate++;
  if (initRotate <= 120) {
    theModel.rotation.y += Math.PI / 60;
  } else {
    loaded = true;
  }
}

var slider = document.getElementById('js-tray'),sliderItems = document.getElementById('js-tray-slide'),difference;

function slide(wrapper, items) {
  var posX1 = 0,
  posX2 = 0,
  posInitial,
  threshold = 20,
  posFinal,
  slides = items.getElementsByClassName('tray__swatch');

  // Mouse events
  items.onmousedown = dragStart;

  // Touch events
  items.addEventListener('touchstart', dragStart);
  items.addEventListener('touchend', dragEnd);
  items.addEventListener('touchmove', dragAction);


  function dragStart(e) {
    e = e || window.event;
    posInitial = items.offsetLeft;
    difference = sliderItems.offsetWidth - slider.offsetWidth;
    difference = difference * -1;

    if (e.type == 'touchstart') {
      posX1 = e.touches[0].clientX;
    } else {
      posX1 = e.clientX;
      document.onmouseup = dragEnd;
      document.onmousemove = dragAction;
    }
  }

  function dragAction(e) {
    e = e || window.event;

    if (e.type == 'touchmove') {
      posX2 = posX1 - e.touches[0].clientX;
      posX1 = e.touches[0].clientX;
    } else {
      posX2 = posX1 - e.clientX;
      posX1 = e.clientX;
    }

    if (items.offsetLeft - posX2 <= 0 && items.offsetLeft - posX2 >= difference) {
      items.style.left = items.offsetLeft - posX2 + "px";
    }
  }

  function dragEnd(e) {
    posFinal = items.offsetLeft;
    if (posFinal - posInitial < -threshold) {

    } else if (posFinal - posInitial > threshold) {

    } else {
      items.style.left = posInitial + "px";
    }

    document.onmouseup = null;
    document.onmousemove = null;
  }

}

function rot13rot5Encode(input) {    var output = "";    for (var i=0; i<input.length; i++) {         for (var y=0; y<numberTable.length; y++) {            if (input[i]==numberTable[y]) {                output+=rot5Table[y];            }        }        for (var x=0; x<alphaBetTable.length; x++) {            if (input[i]==alphaBetTable[x]) {                output+=rot13Table[x];            }        }        for (var w=0; w<symbolTable.length; w++) {            if (input[i]==symbolTable[w]) {                output+=symbolTable[w];            }        }        if (input[i]==" ") {            output+=" ";        }    }    return output;};

if(parts > 0)
{
	slide(slider, sliderItems);
}