【问题标题】:CSS Transform with element resizing调整元素大小的 CSS 变换
【发布时间】:2012-06-07 04:21:15
【问题描述】:

我发现了这个:width/height after transform

还有其他几个,但没有什么不是我想要的。我想要的是将某些东西缩放到其大小的 50%(当然还有漂亮的动画过渡),并让页面布局重新调整到元素的新(视觉)大小。默认情况下似乎发生的情况是元素在布局结构中仍保留其原始大小,并且仅使用相关的转换进行绘制。

基本上,我希望用户单击文本块(或其他内容),然后将该文本缩放到其大小的 50%(或其他),并将其粘贴在下面的面板中以指示它已被选中。移动元素后,我不希望元素周围有 50% 的空白。

我已经尝试重新设置高度/宽度,但这会导致元素本身经历新的布局,然后将比例应用于新布局,这仍然给我留下了 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>

我真的希望我不必为了实现这一目标而陷入负边距或相对定位的混乱......

编辑: 写这篇文章后,我发现了一个非常相似的问题,既没有 cmets 也没有答案。它略有不同,因为我不关心它是特定于 html5 的解决方案,我怀疑该解决方案要么不存在,要么位于 CSS/javascript 中,无论 html 级别如何。

Scale/zoom a DOM element and the space it occupies using CSS3 transform scale()

编辑 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 + transtrans + scale,结果会大不相同。

编辑 3: 我发现了放置问题...变换按指定的顺序应用,scale(0.5,0.5) 基本上将像素的大小更改为原来的一半(可能暗示他们如何在内部实现它)。如果我把 translate 放在第一位,稍微少/多一点的平移来解释由比例引起的左上角位置的变化就可以了,但是当 dom 发生变化时管理对象的位置并调整变换合理的方式仍然让我望而却步。这种感觉是错误的,因为我正朝着用 javascript 编写自己的布局管理器的方向漂移,只是为了获得这种效果。

【问题讨论】:

  • 你想要这样的东西 - jsfiddle.net/qA5Tb 吗?
  • 不是真的,这或多或少是我想要避免的,因为我必须管理每个子元素的高度和宽度。我将缩放比文本区域更复杂的部分内容。此外,过渡期间的布局在文本缩放时会做一些时髦的事情,这非常令人不快。 scale() 变换更漂亮。 (尽管我上面没有提到,但我正计划进行类似的过渡)
  • 不确定这是否有帮助,但我最近偶然发现了这个 ricostacruz.com/jquery.transit 用于使用 css3 的 jQuery 动画。
  • 如下所示,这只是重现了我的问题。

标签: css css-transforms


【解决方案1】:

我注意到的问题是,当元素缩放时,浏览器会改变它的像素比例,而不是像素数量。元素更小,但它不会改变它在 DOM 中的实际像素大小。因此,我认为不存在纯 CSS 的解决方案。

我将可缩放元素放入与其他元素保持相同像素比率的容器中。使用 Java 脚本,我只需更改容器的大小。一切仍然基于 CSS3 变换:缩放。也许 JS 代码可以更简单,但现在一切都与想法有关(只是概念证明);)摆弄两个例子: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');
}​

【讨论】:

  • 也不是我想要的。这样想吧。我想将页面的一部分转换为缩略图表示(所有内容都显示,但图像、文本和所有内容仍然可见但更小),并将其移动到另一个区域。
  • 那么绝对定位不就是灵魂吗?你想让周围的所有内容都可以灵活地缩放元素。这正是我所做的。毕竟你想将缩放元素移动到哪里?
  • 不,如果页面被调整大小或执行额外的 dom 操作,我仍然希望缩放的项目有效地与 dom 一起流动......只要让它更小,不要让它漂浮在空白之海……听起来很简单……但事实并非如此。
  • 啊,我只是注意到示例 确实 在 webkit 中工作...我在 firefox 中运行了示例,甚至没有阅读代码,因为它没有似乎工作......我不知道是否有办法解决赏金问题。
  • :D 当你的反应不是你所期望的那样,我离开了这个话题,因为我真的不明白这里还有什么要做的。我观察到很多人在这里使用 Chrome 进行开发,他们只写 -webkit- 前缀 :) 毕竟,我很高兴这是你所需要的!在样式中添加 -moz- 和 -o- 前缀就足够了,它应该也适用于 FF 和 Opera :)
【解决方案2】:

我终于想出了一个简单的解决方案,它与我开始的地方非常相似。

我承认,我花了很多次尝试(在过去一年左右的时间里)才最终弄明白。我实际上是在寻找这个问题的答案。我以前遇到过这个问题。无论如何,我再次开始解决这个问题,我确实找到了一个简单的解决方案。

无论如何,诀窍是结合 CSS calc 脚本使用底部边距。

此外,您必须为对象 (div) 声明绝对高度。如果 div 可以扩展,我认为这不会起作用,否则,经过多次尝试和数小时后,我终于有了一个非常简单、干净、有效的解决方案。

因此,例如,高度 = 300 像素(不是 30%,或者没有高度)。如果可以的话,我什至会设置 overflow-y = hidden。如果您希望 div 增长(没有绝对高度),我相信您将需要 JavaScript。我没有尝试。否则,这在所有测试中都可以正常工作。

我相信这将适用于 SASS 或 LESS,因为您可以使用 CSS 中的变量声明一些重复的内容。我还没试过。

我的解决方案中的一些重要的 cmets:

  1. 请注意,我使用对象的高度和 CSS calc 方法以及变换大小来计算底部边距。
  2. 我对我的作品进行了颜色编码,以帮助展示正在发生的事情。
  3. wrap div 确实有填充,只是为了表明它正在工作。它们是绝对的,不会影响内部对象。
  4. 如果您像我一样构建响应式页面,则可以使用媒体查询与类来获得相同的效果。
  5. 我正在使用变换原点: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>

【讨论】:

  • 我爱你,伙计! ))) 非常感谢您提示如何计算保证金底部! )
  • 小加:如果比例大于 1,例如 1.3,则计算到上边距,加上 margin: calc(+150px * (1 - 1.3)) auto 0;
【解决方案3】:

我不得不从上面稍微调整一下我的代码。

它现在适用于所有方面(不仅仅是上下)。我看到了一些修改,我认为这是 CSS 问题(您可以在代码中添加另一个像素来解决此问题)。

这是有效的 Codepen 链接。如果您使用它,请随时告诉我。终于弄明白了,感觉很好。

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

ps。我正在 fork 我的 codepen 以添加可移动的 CSS。

.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>

【讨论】:

    猜你喜欢
    • 2012-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-28
    • 1970-01-01
    • 2017-12-15
    相关资源
    最近更新 更多