自定义元素优化文字在圆环内排版实例页面

回到相关文章 »

效果:

在CSS Shapes布局问世之前,文字像杂志一样的任意形状的排版几乎是不可能的,一直都是用网格、盒子和直线构造。CSS Shapes允许我们定义文本环绕的几何形状。这些形状可以是圆、椭圆、简单或复杂的多边形,甚至是任意的图像和多彩的渐变。

代码:

CSS代码:
zxx-circle {
    display: block;
    width: 207px; height: 250px;
    color: white;
    background-color: deepskyblue;
    text-shadow: 1px 1px rgba(0,0,0,.5);
    padding: 10px;
    text-align: justify;
}
HTML代码:
<zxx-circle>在CSS Shapes布局问世之前,文字像杂志一样的任意形状的排版几乎是不可能的,一直都是用网格、盒子和直线构造。CSS Shapes允许我们定义文本环绕的几何形状。这些形状可以是圆、椭圆、简单或复杂的多边形,甚至是任意的图像和多彩的渐变。</zxx-circle>
JS代码:
class HTMLZxxCircleElement extends HTMLElement {
  constructor() {
    self = super();

    let shadow = this.attachShadow({
        mode: 'open'
    });
    
    // 文本内容移动到shadow dom元素中
    let style = document.createElement('style');
    shadow.appendChild(style);
    // 前后元素
    let before = document.createElement('zxx-before');
    let after = document.createElement('zxx-after');
    shadow.prepend(after);
    shadow.prepend(before);
    
    // 内容
    let content = document.createElement('div');
    shadow.appendChild(content);

    let ro = new ResizeObserver( entries => {
      for (let entry of entries) {
        self._updateRendering();
      }
    });
    
    // 观察当前元素尺寸变化
    ro.observe(this);
  }
  
  connectedCallback() {
    // 执行渲染更新
    this._updateRendering();
  }
  _updateRendering() {
    // 根据变化的属性,改变组件的UI
    let shadow = this.shadowRoot;
    let content = shadow.querySelector('div');
    let before = shadow.querySelector('zxx-before');
    before.style.height = 'auto';
    // 内容更新
    content.innerHTML = this.innerHTML;
    // 此时内容高度
    let heightContent = parseFloat(getComputedStyle(content).height);
    let heightBefore = parseFloat(getComputedStyle(before).height);
    
    if (heightContent == 0) {
        return;
    }
    
    // 没有设置具体的高度值
    if (heightBefore == 0 && heightContent != 0) {
        // 同样面积的椭圆的高度是?
        // s = π×a×b
        let height = (2 *  heightContent * 2 / Math.PI) + 'px';
        
        console.warn('<zxx-circle> no height, set it to ' + height + '!');
        this.style.height = height;
    }
    before.removeAttribute('style');
    // 样式设置
    shadow.querySelector('style').textContent = `:host {
    border-radius: 50%;
}
zxx-before,
zxx-after {
    width: 50%; min-height: 100%; height: ${heightContent}px;
}
zxx-before {
    float: left;
    shape-outside: radial-gradient(farthest-side ellipse at right, transparent 100%, red);
}
zxx-after {
    float: right;
    shape-outside: radial-gradient(farthest-side ellipse at left, transparent 100%, red);
}`;
  }
}
// 定义zxx-circle标签元素
customElements.define('zxx-circle', HTMLZxxCircleElement);