web-dev-qa-db-ja.com

要素のサイズ変更によるCSS変換

私はこれを見つけました: 変換後の幅/高さ

他にもいくつかありますが、私が探しているものとはまったく異なります。私が欲しいのは、何かをそのサイズの50%にスケーリングし(もちろん、ニースのアニメーション化されたトランジションを使用)、ページレイアウトを要素の新しい(視覚的な)サイズに再調整することです。デフォルトで起こるように思われるのは、要素がまだレイアウト構造で元のサイズを保持し、関連する変換で描画されるだけであるということです。

基本的に、ユーザーにテキストのブロック(または他のコンテンツ)をクリックしてから、そのテキストをそのサイズの50%(または何でも)に拡大縮小し、選択されたことを示すために下のパネルに貼り付けます。要素を移動した後、要素の周囲に50%の空白が必要ではありません。

高さ/幅を再設定しようとしましたが、それにより要素iselfが新しいレイアウトになり、スケールが新しいレイアウトに適用され、すべてが終了した後も50%の空白が残ります。私のmozilla固有の(簡単にするために)コードは次のようになります。

_<script type="text/javascript">
 function zap(e) {

  var height = e.parentNode.offsetHeight/2 + 'px';
  var width = e.parentNode.offsetWidth/2 + 'px';
  e.parentNode.style.MozTransform='scale(0.0)'; 
  e.parentNode.addEventListener(
    'transitionend', 
    function() { 
      var selectionsArea = document.getElementById("selected");
      selectionsArea.appendChild(e.parentNode);
      e.parentNode.style.MozTransform='scale(0.5,0.5)'; 
      e.parentNode.style.display = 'inline-block';
      e.parentNode.style.height = height;
      e.parentNode.style.width = width;
    },
    true) 
}
</script>
_

私はこれを達成するために負のマージンや相対的な位置をいじり回す必要がないことを本当に望んでいます...

Edit:これを書いてから、コメントも回答もなかった非常によく似た質問を見つけました。私はそれがhtml5固有のソリューションであることを気にしないのでわずかに異なりますが、htmlレベルに関係なくCSS/javascriptに存在しないか、またはソリューションがあると思います。

CSS3 transform scale()を使用してDOM要素とそれが占めるスペースを拡大縮小/ズーム

編集2:(別の非動作の試み)

私もこれを試しましたが、スケールと変換関数は最終位置を予測することを不可能にする方法で相互作用しているように見えます...そして、変換前のスケールは変換してからスケールするように見えません。残念ながら、スケールファクターによる変換の調整だけではありません...

_function posX(e) {
    return e.offsetLeft + (e.offsetParent ? posX(e.offsetParent) : 0)
}

function posY(e) {
    return e.offsetTop + (e.offsetParent ? posY(e.offsetParent) : 0)
}

function placeThumbNail(e, container, x, y, scale) {
    var contX = posX(container);
    var contY = posY(container);
    var eX = posX(e);
    var eY = posY(e);
    var eW = e.offsetWidth;
    var eH = e.offsetHeight;

    var margin = 10;
    var dx = ((contX - eX) + margin + (x * eW * scale));
    var dy = ((contY - eY) + margin + (y * eH * scale));

    // assumes identical objects     
    var trans = 'translate(' + dx + 'px, ' + dy + 'px) ';
    var scale = 'scale(' + scale + ',' + scale + ') ';
    e.style.MozTransform =  trans + scale ; 
}
_

それが機能したとしても、上記では、このコードを実行する前に(空白を取り除くために)最初に要素をページの下部に移動する必要があり、さらに、サイズ変更時に変換を再計算する必要があります。 。とにかく始めようとするこの試みにはあまり満足していませんでした。

また、_scale + trans_と__trans + scale_を使用すると、結果が大幅に異なることに注意してください。

Edit 3:配置の問題を見つけました...変換は指定された順序で適用され、scale(0.5,0.5)は本質的にピクセルのサイズを元のサイズの半分にします(おそらく、内部での実装方法を示唆しています)。翻訳を最初にすると、スケールによって引き起こされる左上隅の位置の変化を考慮してわずかに少ない/より多くの翻訳がトリックになりますが、オブジェクトの場所を管理し、domが合理的な方法はまだ私を避けています。私はこの効果を得るためだけにJavaScriptで独自のレイアウトマネージャーを作成する方向にドリフトしているため、この種の誤りを感じています。

51
Gus

私が気づいた問題は、要素が拡大縮小すると、ブラウザはピクセル量ではなくピクセル比を変更することです。要素は小さくなりますが、DOMの実際のピクセルサイズは変わりません。そのため、CSSのみのソリューションが存在するとは思いません。

スケーラブル要素をコンテナに配置し、他の要素と同じピクセル比を維持します。 Java Scriptを使用して、コンテナのサイズを変更します。すべてはまだCSS3変換に基づいています:スケール。 )Fiddle 2つの例: http://jsfiddle.net/qA5Tb/9/

HTML:

<div class="overall-scalable">
    <div class="scalable" scalex='0.5' scaley='0.5'>
        Nunc et nisi ante. Integer in blandit nisi. Nulla facilisi. Vestibulum vulputate sapien eget mauris elementum sollicitudin. Nullam id lobortis dolor. Nulla vitae nibh vitae sem volutpat pretium. Nunc et nisi ante. Integer in blandit nisi. Nulla facilisi. Vestibulum vulputate sapien eget mauris elementum sollicitudin. Nullam id lobortis dolor. Nulla vitae nibh vitae sem volutpat pretium.
    </div>
</div>

CSS:

.overall-scalable {width: 350px; height: 150px; overflow: hidden; -webkit-transition: all 1s;}
.scalable {color: #666; width: 350px; height: 150px; -webkit-transform-Origin: top left; -webkit-transition: all 1s;}

JS:

$('button').click(function() {
    $('.scalable').each(function(){
        rescale($(this));
    })
});

function rescale(elem) {

    var height = parseInt(elem.css('height'));
    var width = parseInt(elem.css('width'));
    var scalex = parseFloat(elem.attr('scalex'));
    var scaley = parseFloat(elem.attr('scaley'));

    if (!elem.hasClass('rescaled')){
        var ratioX = scalex;
        var ratioY = scaley;
    }else{          
        var ratioX = 1;
        var ratioY = 1;
    }

    elem.toggleClass('rescaled');
    elem.css('-webkit-transform', 'scale('+ratioX +', '+ratioY+')');        
    elem.parent().css('width', parseInt(width*ratioX) + 'px');
    elem.parent().css('height', parseInt(height*ratioY) + 'px');
}​
40
Sófka

私は最終的に簡単な解決策を見つけましたが、それは私が始めた場所と非常に似ています

私は認めます、最終的にそれを理解するために(昨年かそこらで)これを理解するために多くの試みをしました私は実際にこの質問に対する答えを探していました。私は以前これに問題がありました。とにかく、私は再びこれを解決し始め、簡単な解決策を見つけました。

とにかく、CSS calcスクリプトと一緒にマージン下部を使用するのがコツです。

また、オブジェクト(div)に対して絶対高さを宣言する必要があります。 divが拡張できる場合、これがうまくいくとは思いません。

したがって、たとえば、高さ= 300ピクセル(30%ではなく、高さなし)。可能であれば、overflow-y = hiddenも設定します。 divを(絶対的な高さではなく)成長させたい場合、JavaScriptが必要になると思います。私はそれを試しませんでした。それ以外の場合、これはすべてのテストで正しく機能しています。

CSSの変数を使用して繰り返しのいくつかを宣言できるので、これはSASSまたはLESSでうまく機能すると確信しています。私はまだ試していません。

私のソリューションに関するいくつかの重要なコメント:

  1. オブジェクトの高さとCSS calcメソッドを変換サイズとともに使用して、下マージンを計算していることに注意してください。
  2. 何が起きているかを示すために、作業を色分けしました。
  3. ラップdivにはパディングがあり、機能していることを示すためだけにあります。これらは絶対的なものであり、内部オブジェクトには影響しません。
  4. 私のようにレスポンシブページを構築している場合、メディアクエリとクラスを使用して同じ効果を得ることができます。
  5. Transform-Originを使用しています:50%0;このコードは、当初考えていたほど重要ではありませんでした。私が持っていた問題を解決するために、下マージンを使用しています。
  6. この例では、divを親divの中央に配置しています。 divを配置する必要がある場合は、もう少し複雑ですが、同様のソリューションが機能します。私はそれを試みませんでした。
  7. この同じソリューションをjQueryとCSSで使用できます。考え方は同じです。ページ内の変換ですべての要素を検索し、必要に応じてCSSを追加します。

また、これをテストして共有するためのCodepenをセットアップしました。

https://codepen.io/cyansmiles/details/yvGaVP

.box-wrap {
  display: block;
  position: relative;
  box-sizing: border-box;
  width: 100%;
  margin: auto;
  text-align: center;
  margin: 30px 10px;
  padding: 40px;
  background: yellow;
}

.box-wrap:before {
  content: "";
  display: block;
  box-sizing: border-box;
  position: absolute;
  background: rgba(0, 0, 0, 0.5);
  width: calc(100% - 80px);
  height: calc(100% - 80px);
  top: 40px;
  left: 40px;
}

.box {
  display: inline-block;
  box-sizing: border-box;
  position: relative;
  transform-Origin: 50% 0;
  width: 300px;
  height: 150px;
  background: red;
}

.box.size-80 {
  transform: scale(0.8);
  margin: 0 auto calc(-150px * (1 - 0.8));
}

.box.size-70 {
  transform: scale(0.7);
  margin: 0 auto calc(-150px * (1 - 0.7));
}

.box.size-60 {
  transform: scale(0.6);
  margin: 0 auto calc(-150px * (1 - 0.6));
}

.box.size-50 {
  transform: scale(0.5);
  margin: 0 auto calc(-150px * (1 - 0.5));
}

//etc
<div class="box-wrap">
  <div class="box">
    <h1>Box at 100%</h1>
  </div>
</div>

<div class="box-wrap">
  <div class="box size-80">
    <h1>Box at 80%</h1>
  </div>
</div>

<div class="box-wrap">
  <div class="box size-70">
    <h1>Box at 70%</h1>
  </div>
</div>

<div class="box-wrap">
  <div class="box size-60">
    <h1>Box at 60%</h1>
  </div>
</div>

<div class="box-wrap">
  <div class="box size-50">
    <h1>Box at 50%</h1>
  </div>
</div>
2
Nathan Sharfi

上から少しコードを微調整する必要がありました。

上下だけでなく、すべての側面で機能するようになりました。私は少し編集を見ています、それはCSSの問題だと思います(これを解決するためにコードに別のピクセルを追加することができます)。

動作するCodepenリンクは次のとおりです。それを使用するかどうか私に知らせてください。これを最終的に理解できて良かった。

https://codepen.io/cyansmiles/pen/bLOqZo

追伸移動可能なCSSを追加するようにcodepenにフォークしています。

.box-wrap {
  display: block;
  position: relative;
  box-sizing: border-box;
  width: 100%;
  margin: auto;
  text-align: center;
  margin: 30px 10px;
  padding: 40px;
  background: yellow;
}

.box-wrap:before {
  content: "";
  display: block;
  box-sizing: border-box;
  position: absolute;
  background: rgba(0, 0, 0, 0.5);
  width: calc(100% - 80px);
  height: calc(100% - 80px);
  top: 40px;
  left: 40px;
}

.box {
  display: inline-block;
  box-sizing: border-box;
  position: relative;
  transform-Origin: 50% 0;
  width: 300px;
  height: 150px;
  background: red;
  color: #fff;
}

.box.size-80 {
  background: red;
  transform: scale(0.8);
  margin: 0 calc((-300px * (1 - 0.8)) / 2) calc(-150px * (1 - 0.8));
}

.box.size-70 {
  background: blue;
  transform: scale(0.7);
  margin: 0 calc((-300px * (1 - 0.7)) / 2) calc(-150px * (1 - 0.7));
}

.box.size-60 {
  background: green;
  transform: scale(0.6);
  margin: 0 calc((-300px * (1 - 0.6)) / 2) calc(-150px * (1 - 0.6));
}

.box.size-50 {
  background: orange;
  transform: scale(0.5);
  margin: 0 calc((-300px * (1 - 0.5)) / 2) calc(-150px * (1 - 0.5));
}

//etc
<div class="box-wrap">
  <h1>This is a bunch of boxes!</h1>
  <div class="box size-50">
    <h1>Box at 50%</h1>
  </div>
  <div class="box size-60">
    <h1>Box at 60%</h1>
  </div>
  <div class="box size-80">
    <h1>Box at 80%</h1>
  </div>
  <div class="box size-70">
    <h1>Box at 70%</h1>
  </div>
  <div class="box size-50">
    <h1>Box at 50%</h1>
  </div>
  <div class="box size-60">
    <h1>Box at 60%</h1>
  </div>
  <div class="box size-50">
    <h1>Box at 50%</h1>
  </div>
  <div class="box size-60">
    <h1>Box at 60%</h1>
  </div>
  <div class="box size-80">
    <h1>Box at 80%</h1>
  </div>
  <div class="box size-70">
    <h1>Box at 70%</h1>
  </div>
  <div class="box size-50">
    <h1>Box at 50%</h1>
  </div>
  <div class="box size-60">
    <h1>Box at 60%</h1>
  </div>
</div>

<div class="box-wrap">
  <div class="box">
    <h1>Box at 100%</h1>
  </div>
</div>

<div class="box-wrap">
  <div class="box size-80">
    <h1>Box at 80%</h1>
  </div>
</div>

<div class="box-wrap">
  <div class="box size-70">
    <h1>Box at 70%</h1>
  </div>
</div>

<div class="box-wrap">
  <div class="box size-60">
    <h1>Box at 60%</h1>
  </div>
</div>

<div class="box-wrap">
  <div class="box size-50">
    <h1>Box at 50%</h1>
  </div>
</div>
0
Nathan Sharfi