Circles 2

by whelkaholism

HTML

<div class="c">
  <div data-bind="circles: items, circlesConfig: config"></div>
</div>

CSS

.c {
  display: flex;
  height: 100vh;
  align-items: center;
  justify-content: center;  
}
.circles-root {
  display: flex;
  align-items: center;
  justify-content: center;
  color: #ffffff;
  font-weight: 900;
  font-size: 20px;
  position: relative;
  background: red;
  border-radius: 50%;
  width: 50vh;
  height: 50vh;
}

.circles-root > .circles-sub-circle {
  position: absolute;
  top: 50%;
  left: 50%;
  background: blue;
  border-radius: 50%;
  width: 25vh;
  height: 25vh;
  margin-left: -25%;
  margin-top: -25%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #ffffff;
  font-size: 32px;
}

.circles-root > .circles-sub-circle:hover {
  opacity: 0.5;
}

JavaScript

(function() {
window.Circles = function(el, cfg)
{
  const _this = this;
  const _cfg = cfg;
  this.element = el;
  const _items = [];
  
  this.setItems = function(items)
  {
    _items.length = 0;
    items.forEach(function(x) {
        _items.push({
            content: x.content,
            data: x
        });
    });
  };

  this.clear = function() {
    _this.element.replaceChildren();
  };

  this.redraw = function() {
    _this.clear();
    _this.render();
  };

  this.render = function()
  {
    if(_cfg.root)
    {
      _this.contentElement = document.createElement('div');    
      _this.contentElement.classList.add('circles-root-content');            
      _this.contentElement.innerHTML = ko.unwrap(_cfg.root.content) || '';

      _this.element.appendChild(_this.contentElement);

      _cfg.root.rendered && _cfg.root.rendered(_this.element, _this.contentElement);
      _cfg.root.click && _this.element.addEventListener('click', _cfg.root.click.bind(_this, _cfg.root));
    }

    const angle = 360 / _items.length;
    let curr = 0;

    _items.forEach(function(x) {
        x.element = document.createElement('div');
        x.element.classList.add('circles-sub-circle'); 
        x.data.click && x.element.addEventListener('click', x.data.click.bind(_this, x.data));

        const rot = curr > 0 ? `rotate(${curr}deg) ` : '';
        x.element.style.transform = `${rot}translateY(-100%)`;

        x.contentElement = document.createElement('div');    
        x.contentElement.classList.add('circles-sub-circle-content');            
        x.contentElement.innerHTML = ko.unwrap(x.content) || '';
        x.contentElement.style.transform = `rotate(-${curr}deg)`;

        x.element.appendChild(x.contentElement);
        _this.element.appendChild(x.element);

        x.data.rendered && x.data.rendered(x.element, x.contentElement);

        curr += angle;
    });
  };

 ...