meo
meo

Reputation: 31249

How to use clip-path polygons in FF and IOS

I try to write a little plugin, to open modal boxes in a more organic fashion, therefore I have decided to animate the clip-path property.

Now this code only works in chrome: http://codepen.io/meodai/pen/GgGzYo?editors=011

It looks like firefox does not support polygon() in the clip-path property. Safari & Mobile Safari do struggle with it as well.

Is there a similarly easy way to make this work in Firefox and Safari and Mobile Safari as well? Any idea how I could approach this problem?

Here is a working example:

var $ov = $('.overlay');

$(document).on('click touchstart', '.inner', function(){
  var coords, coordArray, coordsString;

  coords = this.getBoundingClientRect();

  coordArray = [
    Math.floor(parseInt(coords.left)) + 'px ' + Math.floor(parseInt(coords.top)) + 'px',
    Math.ceil((parseInt(coords.left) + parseInt(coords.width))) + 'px ' + Math.ceil(parseInt(coords.top)) + 'px',
    Math.ceil((parseInt(coords.left) + parseInt(coords.width))) + 'px ' + Math.ceil((parseInt(coords.top) + parseInt(coords.height) )) + 'px',
    Math.ceil(parseInt(coords.left)) + 'px ' + Math.floor((parseInt(coords.top) + parseInt(coords.height) )) + 'px'
  ];


  coordsString = 'polygon(' + coordArray[0] + ',' + coordArray[1] + ',' + coordArray[2] + ',' + coordArray[3] + ')';

  $ov.css({
    '-webkit-clip-path': coordsString,
    'clip-path': coordsString
  });

  setTimeout(function(){
    $ov.addClass('show');
  },50);

  setTimeout(function(){
    coordsString = 'polygon(0% 0%,' + coordArray[1] + ',' + coordArray[2] + ',' + coordArray[3] + ')';
    $ov.css({
      '-webkit-clip-path': coordsString,
        'clip-path': coordsString
    });
  },100);
  setTimeout(function(){
    coordsString = 'polygon(0% 0%,100% 0%,' + coordArray[2] + ',' + coordArray[3] + ')';
    $ov.css({
      '-webkit-clip-path': coordsString,
        'clip-path': coordsString
    });
  },180);
  setTimeout(function(){
    coordsString = 'polygon(0% 0%,100% 0%,100% 100%,' + coordArray[3] + ')';
    $ov.css({
      '-webkit-clip-path': coordsString,
        'clip-path': coordsString
    });
  },260);

  setTimeout(function(){
    coordsString = 'polygon(0% 0%,100% 0%,100% 100%,0 100%)';
    $ov.css({
      '-webkit-clip-path': coordsString,
        'clip-path': coordsString
    });
  },340);

  // reverse
  setTimeout(function(){
    coordsString = 'polygon(0% 0%,100% 0%,100% 100%,' + coordArray[3] + ')';
    $ov.css({
      '-webkit-clip-path': coordsString,
        'clip-path': coordsString
    });
  },1500);

  setTimeout(function(){
    coordsString = 'polygon(0% 0%,100% 0%,' + coordArray[2] + ',' + coordArray[3] + ')';
    $ov.css({
      '-webkit-clip-path': coordsString,
        'clip-path': coordsString
    });
  },1580);
  setTimeout(function(){
    coordsString = 'polygon(0% 0%,' + coordArray[1] + ',' + coordArray[2] + ',' + coordArray[3] + ')';
    $ov.css({
      '-webkit-clip-path': coordsString,
        'clip-path': coordsString
    });
  },1640);
  setTimeout(function(){
    coordsString = 'polygon(' + coordArray[0] + ',' + coordArray[1] + ',' + coordArray[2] + ',' + coordArray[3] + ')';
    $ov.css({
      '-webkit-clip-path': coordsString,
        'clip-path': coordsString
    });
  },1740);



   setTimeout(function(){
    $ov.removeClass('show');
  },2000);

});
body, html {
  background: silver;
}

.grid {
  float: left;
  width: 25%;
  height: 25vw;
  box-shizing: border-box;
  position: relative;
}

.inner {
  position: absolute;
  top: 10px;
  left: 10px;
  bottom: 10px;
  right: 10px;
  background: #ddd;
  -webkit-transition: background-color 111ms;
          transition: background-color 111ms;
}
.inner:hover {
  background: #fff;
}

.overlay {
  opacity: 0;
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background: #fff;
  pointer-events: none;
  box-sizing: border-box;
  padding: 20px;
}

.overlay.show {
  opacity: 1;
  will-change: clip-path;
  -webkit-transition: clip-path 200ms;
          transition: clip-path 200ms;
  -webkit-transition: -webkit-clip-path 200ms;
          transition: -webkit-clip-path 200ms;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="grid">
  <div class="inner"></div>
</div>
<div class="overlay"></div>

Upvotes: 8

Views: 6961

Answers (4)

asking for a friend
asking for a friend

Reputation: 191

I had this problem where my clipped element was not showing as clipped on iPhoneX.

Adding webkit solved it for me:

clip-path: polygon(0 0, 0% 100%, 100% 0); -webkit-clip-path: polygon(0 0, 0% 100%, 100% 0);

Upvotes: 3

web-tiki
web-tiki

Reputation: 103780

You might want to take a look at svgs as you can animate the points of a polygon and morph it to the desired shape.

DEMO

DEMO With images and titles

This demo uses the snap.svg library to make the squares and manipulate them on the click event.
It is currently not finished and there are some bugs but you should get the idea.

I totaly refactored the code, thanks to rlemon for helping me get it way better. I tested it in latest FF and Chrome and a user reported it works on an iphone with safari.

The items are made with polygons, a square polygon is added on click and it's points are animated one by one to be featured.

var items = [
  [ 1, 1,24, 1,24,24, 1,24],
  [26, 1,49, 1,49,24,26,24],
  [51, 1,74, 1,74,24,51,24],
  [76, 1,99, 1,99,24,76,24],
  [ 1, 26,24, 26,24,49, 1,49],
  [26, 26,49, 26,49,49,26,49],
  [51, 26,74, 26,74,49,51,49],
  [76, 26,99, 26,99,49,76,49],
  [ 1, 51,24, 51,24,74, 1,74],
  [26, 51,49, 51,49,74,26,74],
  [51, 51,74, 51,74,74,51,74],
  [76, 51,99, 51,99,74,76,74],
  [ 1, 76,24, 76,24,99, 1,99],
  [26, 76,49, 76,49,99,26,99],
  [51, 76,74, 76,74,99,51,99],
  [76, 76,99, 76,99,99,76,99]
],
    item = [],points= [],i, p=[],open = 0,
    s = Snap().attr({viewBox:"0 0 100 100","fill":"#585247"});

function runAnimations(el) {
  if( !animationSequences.length ) return;
  var sequence = animationSequences.shift();
  el.animate(sequence,120,mina.linear, runAnimations.bind(null,el));
}


function register(x,i) {
  item[i] = s.polygon(items[i]);  
  item[i].click(function () {
    var featured = s.polygon(items[i]).attr({"fill":"#585247"});
    p = items[i];
    animationSequences = [
      {"points": p[0]/2+","+p[1]/2+","+p[2]+","+p[3]+","+p[4]+","+p[5]+","+p[6]+","+p[7]},
      {"points": p[0]/3+","+p[1]/3+",100,0,100,100,"+p[6]+","+p[7]},
      {"points": p[0]/4+","+p[1]/4+",100,0,100,100,0,100"},
      {"points": "0,0,100,0,100,100,0,100"},
    ];
    runAnimations(featured);
    featured.animate({"fill":"#ACA696"},300);
    featured.click(function(){
      this.stop().animate({"points":p,"fill":"#585247"},200,mina.linear,featured.remove);
    });
  });
}
items.forEach(register);
*{margin:0;padding:0;}
body{background:#E3DFD2;}
svg{display:block;}
<script src="http://thisisa.simple-url.com/js/snapsvg.js"></script>

Upvotes: 10

Fer To
Fer To

Reputation: 1517

I've tested a lot of possibilities, but according to http://caniuse.com/#search=polygon polygon is not support in FF (!). I've tried a lot of possibilities but each time the FF dev tools tell me that it is not a correct value.

My tested code (from your codepen):

var $ov = $('.overlay');

$(document).on('click touchstart', '.inner', function(){
  var coords, coordArray, coordsString;
  var windowWidth = window.innerWidth + "";
  coords = this.getBoundingClientRect();

  coordArray = [
    Math.floor(parseInt(coords.left)) + ' ' + Math.floor(parseInt(coords.top)) + '',
    Math.ceil((parseInt(coords.left) + parseInt(coords.width))) + ' ' + Math.ceil(parseInt(coords.top)) + '',
    Math.ceil((parseInt(coords.left) + parseInt(coords.width))) + ' ' + Math.ceil((parseInt(coords.top) + parseInt(coords.height) )) + '',
    Math.ceil(parseInt(coords.left)) + ' ' + Math.floor((parseInt(coords.top) + parseInt(coords.height) )) + ''
  ];


  coordsString = 'polygon(' + coordArray[0] + ',' + coordArray[1] + ',' + coordArray[2] + ',' + coordArray[3] + ')';

  $ov.css({
    '-webkit-clip-path': coordsString,

    'clip-path': coordsString
  });

  setTimeout(function(){
    $ov.addClass('show');
  },50);

  setTimeout(function(){
    coordsString = 'polygon(0 0,' + coordArray[1] + ',' + coordArray[2] + ',' + coordArray[3] + ')';
    $ov.css({
      '-webkit-clip-path': coordsString,

      'clip-path': coordsString
    });
  },100);
  setTimeout(function(){
    coordsString = 'polygon(0 0 ,'+windowWidth+' 0,' + coordArray[2] + ',' + coordArray[3] + ')';
    $ov.css({
      '-webkit-clip-path': coordsString,

      'clip-path': coordsString
    });
  },180);
  setTimeout(function(){
    coordsString = 'polygon(0 0,'+windowWidth+' 0,'+windowWidth+' '+windowWidth+',' + coordArray[3] + ')';
    $ov.css({
      '-webkit-clip-path': coordsString,

      'clip-path': coordsString
    });
  },260);

  setTimeout(function(){
    coordsString = 'polygon(0 0,'+windowWidth+' 0,'+windowWidth+' '+windowWidth+',0 '+windowWidth+')';
    $ov.css({
      '-webkit-clip-path': coordsString,

      'clip-path': coordsString
    });
  },340);

  // reverse
  setTimeout(function(){
    coordsString = 'polygon(0 0,'+windowWidth+' 0,'+windowWidth+' '+windowWidth+',' + coordArray[3] + ')';
    $ov.css({
      '-webkit-clip-path': coordsString,

      'clip-path': coordsString
    });
  },1500);

  setTimeout(function(){
    coordsString = 'polygon(0 0,'+windowWidth+' 0,' + coordArray[2] + ',' + coordArray[3] + ')';
    $ov.css({
      '-webkit-clip-path': coordsString,

      'clip-path': coordsString
    });
  },1580);
  setTimeout(function(){
    coordsString = 'polygon(0 0,' + coordArray[1] + ',' + coordArray[2] + ',' + coordArray[3] + ')';
    $ov.css({
      '-webkit-clip-path': coordsString,

      'clip-path': coordsString
    });
  },1640);
  setTimeout(function(){
    coordsString = 'polygon(' + coordArray[0] + ',' + coordArray[1] + ',' + coordArray[2] + ',' + coordArray[3] + ')';
    $ov.css({
      '-webkit-clip-path': coordsString,

      'clip-path': coordsString
    });
  },1740);



   setTimeout(function(){
    $ov.removeClass('show');
  },2000);

});

Upvotes: 0

Simon Staton
Simon Staton

Reputation: 4505

Clip-path only supports numbers for point values, it looks like you are using percentages/pixel scales which is why it will be failing in firefox.

Change to integer values:

coordsString = 'polygon(0 0,123 0,' + coordArray[2] + ',' + coordArray[3] + ')';
$ov.css({
  '-webkit-clip-path': coordsString,
    'clip-path': coordsString
});

You will need to remove pixel references from the coordArray and calculate actual int values from the percentages.

Upvotes: 7

Related Questions