0

I want to make 2 spans work like a mirror image , when i move one second will have to move in opposite direction

First Span

<span style="transform: translate(-13px, 0px) scale(1, 1) rotate(0deg);">
<img src="./ImageEditor Demo_files/ImageRight.png" style="width: 750px; height: 750px;">
</span>

Second Span

<span style="transform: translate(13px, 0px) scale(-1, -1) rotate(-0deg);">
<img src="./ImageEditor Demo_files/ImageLeft.png" style="width: 750px; height: 750px;">
</span>

logic I am using

var observer1 = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutationRecord) {
      var transform1 = document.getElementsByTagName('span')[3].style.transform;
document.getElementsByTagName('span')[0].style.transform = transform1
      
  });    
});

var target = document.getElementsByTagName('span')[0];

observer.observe(target, { attributes : true, attributeFilter : ['style'] });

It trigger when css of first changes & it change css of 2nd span same as first one but i want it to like if rotate for first is 10deg then for 2nd it should be -10deg, same for translate and scale

Please have a look

Karan Goyal
  • 447
  • 5
  • 10
  • Does this answer your question? [How to set a single value of transform while leaving the other values?](https://stackoverflow.com/questions/13769800/how-to-set-a-single-value-of-transform-while-leaving-the-other-values) – Niklas E. Jun 27 '20 at 09:00
  • 1
    use CSS variables – Temani Afif Jun 27 '20 at 09:34

2 Answers2

1

You can use a regex to extract all the number values from the transform-string and then put them back in after you've inverted/mirrored them:

[mirror].style.transform = [source].style.transform.replace(/[-?\.?\d]+/g,function(match){return -1*Number(match);});
  • This regex pattern (/.../g) basically looks for all (g) numbers (\d+) in the provided string, with optional minus sign (-?) and/or decimal point (\.?).
    See https://regexr.com/57knk for a detailed explanation on how this pattern works.
  • See string.replace() and string.replace() with function for information on how the rest of the replace function works.

In the live snippet below I changed a few other things as well, to make your code more flexible, I'll comment on those changes after the snippet:

document.getElementById('transform').onclick = function(){document.getElementsByClassName('elem source')[0].style.transform = this.previousElementSibling.value;};
/*ONLY FOR DEMO*/

var elemMirror = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    document.getElementsByClassName(mutation.target.className.replace('source','mirror'))[0].style.transform = mutation.target.style.transform.replace(/[-?\.?\d]+/g,function(match){return -1*Number(match);});
  });
});
elemMirror.observe(document.getElementsByClassName('elem source')[0], {attributes:true, attributeFilter:['style']});
form {width:100%; margin-bottom:30px;}
form span {font-weight:bold;}
form input {margin:0; box-sizing:border-box;}
form input[type=text] {width:calc(100% - 50px); font-family:monospace;}
form input[type=button] {width:50px;}
/*ONLY FOR DEMO*/

.elem {
  float: left;
  width: 50%;
  text-align: center;
  transform: translate(0px,0px) scale(1,1) rotate(0deg);
}
.elem img {width:79px; height:79px;}
<form>
  <span>Transform the first, mirror the second:</span><br />
  <input type="text" value="translate(0px,0px) scale(1,1) rotate(0deg)" /><input type="button" id="transform" value="apply" />
</form>
<!--ONLY FOR DEMO-->

<div class="elem source"><img src="https://i.stack.imgur.com/WiZzP.png"></div>
<div class="elem mirror"><img src="https://i.stack.imgur.com/WiZzP.png"></div>
jsfiddle: https://jsfiddle.net/hk2gbuj6/4/
  • Everything above the ONLY FOR DEMO comments is, as stated, only for demonstration purposes so you can play around with it.
  • I changed your span to div, because I couldn't get transform to work on a span.
  • I gave the first div class="elem source", and the second div class="elem mirror".
    The class elem can be whatever your want it to be, just make sure that the source and mirror element both have the same class.
    Then, make sure the original/source element has class source, and the element that is supposed to mirror that original/source element, has class mirror. These two classes will be used in the MutationObserver function to refer to the two elements in a variable way.
  • Now, inside MutationObserver(), instead of hard-coding the source and mirror elements into the function (your ('span')[0] and ('span')[3]), I refer to them in a variable manner:
    1. I use mutation.target to refer to the source element.
    2. I use mutation.target.className.replace('source','mirror') to refer to the mirror element.
    3. So now you only have to change the target when you call MutationObserver.observe():
      elemMirror.observe(document.getElementsByClassName('elem source')[0], {...});


Choose which transform-values to mirror:

If you don't want to mirror all transform-values, but only a selected few, change this:

document.getElementsByClassName(mutation.target.className.replace('source','mirror'))[0].style.transform = mutation.target.style.transform.replace(/[-?\.?\d]+/g,function(match){return -1*Number(match);});

to this:

var mirrorValues = ['translate','rotate']; //transform-values to mirror
var transform = mutation.target.style.transform.split(') ');
transform.forEach(function(item,index) {
  if (mirrorValues.indexOf(item.substring(0,item.indexOf('('))) != -1) {
    transform[index] = item.replace(/[-?\.?\d]+/g,function(match){return -1*Number(match);});
  }
});
document.getElementsByClassName(mutation.target.className.replace('source','mirror'))[0].style.transform = transform.join(') ');

document.getElementById('transform').onclick = function(){document.getElementsByClassName('elem source')[0].style.transform = this.previousElementSibling.value;};
/*ONLY FOR DEMO*/

var elemMirror = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    var mirrorValues = document.getElementById('mirrorValues').value.split(',');
    var transform = mutation.target.style.transform.split(') ');
    transform.forEach(function(item,index) {
      if (mirrorValues.indexOf(item.substring(0,item.indexOf('('))) != -1) {
        transform[index] = item.replace(/[-?\.?\d]+/g,function(match){return -1*Number(match);});
      }
    });
    document.getElementsByClassName(mutation.target.className.replace('source','mirror'))[0].style.transform = transform.join(') ');
  });
});
elemMirror.observe(document.getElementsByClassName('elem source')[0], {attributes:true, attributeFilter:['style']});
form {width:100%; margin-bottom:20px;}
form span {font-weight:bold;}
form input {margin:0; box-sizing:border-box;}
form input[type=text] {width:calc(100% - 50px); font-family:monospace;}
form input[type=button] {width:50px;}
/*ONLY FOR DEMO*/

.elem {
  float: left;
  width: 50%;
  text-align: center;
  transform: translate(0px,0px) scale(1,1) rotate(0deg);
}
.elem img {width:79px; height:79px;}
<form>
  <span>Transform-values to mirror (separate by comma):</span><br />
  <input type="text" id="mirrorValues" value="translate,scale,rotate" /><br />
  <span>Transform the first, mirror the second:</span><br />
  <input type="text" value="translate(0px,0px) scale(1,1) rotate(0deg)" /><input type="button" id="transform" value="apply" />
</form>
<!--ONLY FOR DEMO-->

<div class="elem source"><img src="https://i.stack.imgur.com/WiZzP.png"></div>
<div class="elem mirror"><img src="https://i.stack.imgur.com/WiZzP.png"></div>
jsfiddle: https://jsfiddle.net/hk2gbuj6/5/
  • var mirrorValues = ['translate','rotate']; creates an array with all the transform-values to mirror.
    var mirrorValues = document.getElementById('mirrorValues').value.split(','); is used in the snippet to create an array from the input-field-text.
  • var transform = mutation.target.style.transform.split(') '); creates an array from the source element's transform-property, in which all the individual values are split up as separate array-values.
  • transform.forEach(function(item,index) {...}); then iterates over all the separate values, and
    if (mirrorValues.indexOf(item.substring(0,item.indexOf('('))) != -1) {...} checks whether the value is in the mirrorValues-array.
  • If it is, transform[index] = item.replace(/[-?\.?\d]+/g, ...); will invert/mirror the value.
  • Finally, [mirror].style.transform = transform.join(') '); will put all the separate array-values together again into one single 'transform' string.

See array.indexOf(), string.substring(), string.indexOf(), string.split() and array.join() for more information on all the operations I'm using.

myfunkyside
  • 3,890
  • 1
  • 17
  • 32
0

I solved it by using split

var observer = new MutationObserver(function(mutations) {
  
  arrsplit = document.getElementsByTagName('span')[0].style.transform.split(/[\(,)px]+/);
  replace = arrsplit[7].replace('deg','')
  mirror= arrsplit[0]+"("+parseFloat(arrsplit[1])*-1+"px"+", "+parseFloat(arrsplit[2])*1+"px"+")"
  +arrsplit[3]+"("+parseFloat(arrsplit[4])*1+", "+parseFloat(arrsplit[5])*1+")"+
  arrsplit[6]+"("+parseFloat(replace)*-1+"deg"+")";

  mutations.forEach(function(mutationRecord) {
  document.getElementsByTagName('span')[3].style.transform = mirror
  console.log('style changed!');
}

 var observer1 = new MutationObserver(function(mutations) {
  
  arrsplit = document.getElementsByTagName('span')[3].style.transform.split(/[\(,)px]+/);
  replace = arrsplit[7].replace('deg','')
  mirror= arrsplit[0]+"("+parseFloat(arrsplit[1])*-1+"px"+", "+parseFloat(arrsplit[2])*1+"px"+")"
  +arrsplit[3]+"("+parseFloat(arrsplit[4])*1+", "+parseFloat(arrsplit[5])*1+")"+
  arrsplit[6]+"("+parseFloat(replace)*-1+"deg"+")";
  
  mutations.forEach(function(mutationRecord) {
  var transform1 = document.getElementsByTagName('span')[3].style.transform;
  document.getElementsByTagName('span')[0].style.transform = mirror
  
  });    
  });
  
  var target = document.getElementsByTagName('span')[0];
  var target2 = document.getElementsByTagName('span')[3];
  observer1.observe(target2, { attributes : true, attributeFilter : ['style'] });
  observer.observe(target, { attributes : true, attributeFilter : ['style'] });
Karan Goyal
  • 447
  • 5
  • 10