user5988442
user5988442

Reputation:

How do I get text wrap in a circle shape?

I want to wrap text around a circular image with the help of CSS or JavaScript like you can see below.

#corner {
  border-radius: 100%;
  background: url(https://osiprodwusodcspstoa01.blob.core.windows.net/en-us/media/187a9a09-fb97-4a5e-a8a2-620c782d6c67.png);
  background-position: left top;
  background-repeat: repeat;
  padding: 20px;
  width: 150px;
  height: 150px;
}
<p id="corner"></p>

I've searched the Internet but could not fined anything helpful.

Upvotes: 7

Views: 6330

Answers (5)

Ruslan
Ruslan

Reputation: 1303

SVG approach is simple and compact, but what if you need something more flexible? Here is my solution with JavaScript .

window.addEventListener('load', wrap);

function wrap() {
  var image = document.querySelector('#image-to-wrap');
  var text = document.querySelector('#wrapping-text');

  var start = -90;
  var angle = 360;

  var radius = image.clientHeight / 2;
  var centerX = image.getBoundingClientRect().left + radius;
  var centerY = image.getBoundingClientRect().top + radius;
  var characters = text.innerHTML.split('');
  var step = angle / characters.length - 1;

  text.innerHTML = '';

  for (var i = 0; i < characters.length; i++) {
    buildItem(i);
  }

  function buildItem(i) {
    var item = document.createElement('span');
    item.innerHTML = characters[i];
    text.appendChild(item);
    var w = item.clientWidth;
    var h = item.clientHeight;
    var a = (start + step * i) * Math.PI / 180;
    item.style.left = centerX - w / 2 + radius * Math.sin(a) + 'px';
    item.style.top = centerY - h - radius * Math.cos(a) + 'px';
    item.style.transform = 'rotate(' + a + 'rad)';
  }
}
#image-to-wrap {
  height: 250px;
  margin: 50px;
  width: 250px;
}

#wrapping-text {
  color: MistyRose;
  font-family: serif;
  font-size: 50px;
  -webkit-text-stroke: 1px Salmon;
}

#wrapping-text span {
  position: absolute;
  transform-origin: 50% 100%;
}
<img id="image-to-wrap" src="https://upload.wikimedia.org/wikipedia/commons/8/85/Reinel_wind_rose_round.png">
<p id="wrapping-text">Reinel wind rose round</p>

Upvotes: 3

Robert Longson
Robert Longson

Reputation: 123985

You can do this in SVG with a <textPath>. If you use SVG you won't need to break up the text into separate characters. The path is just a circle written using elliptical arc commands.

<svg viewBox="0 0 400 400">
  <defs>
    <path id="MyPath"
          d="M 200, 200
             m -100, 0
             a 100,100 0 1,1 200,0
             a 100,100 0 1,1 -200,0
" />
  </defs>

  <text font-family="Verdana" font-size="30" fill="rgb(248,203,173)" stroke="rgb(237,125,49)">
    <textPath xlink:href="#MyPath">
      I want to bend my text around the circle.
    </textPath>
  </text>
  <circle fill="none" stroke="rgb(165,195,251)" cx="200" cy="200" r="80" stroke-width="10" filter="blur(3px)" />
  <circle fill="rgb(146,208,80)" stroke="rgb(169,209,142)" stroke-width="2px" cx="200" cy="200" r="78" />
</svg>

Upvotes: 17

Hossein Bajan
Hossein Bajan

Reputation: 2792

You can use the transform(rotate) in css3 to do this.

body{
    text-align: center;
    margin-top: 30px;
}
#corner{
    margin-top: 50px;
    background: #92d050;
    width: 150px;
    height: 150px;
    border-radius: 50%;
    display: inline-block;
    -webkit-box-shadow: 0 0 6px 6px #a7c5fb, 0 3px 6px #a7c5fb;
    box-shadow: 0 0 6px 6px #a7c5fb, 0 3px 6px #a7c5fb;
}

.contaner {
    position: relative;
    width: 280px;
    margin: auto;
  }
  
   span {
       font-family: 'sans-serif', Tahoma, Geneva, Verdana, sans-serif;
    position: absolute;
    color: #f8cbad;
    -webkit-text-stroke: 1px #ed7d31;
    font-size: 30px;
  }
  
  .char1 {
    transform: rotate(-90deg);
    left: 26px;
    top: 105px;
  }
  
  .char2 {
    transform: rotate(-72deg);
    left: 21px;
    top: 78px;
  }
  
  .char3 {
    transform: rotate(-56deg);
    left: 33px;
    top: 58px;
  }
  
  .char4 {
    transform: rotate(-56deg);
    left: 44px;
    top: 43px;
  }
  
  .char5 {
    transform: rotate(-49deg);
    left: 57px;
    top: 31px;
  }
  
  .char6 {
    transform: rotate(-37deg);
    left: 72px;
    top: 18px;
  }
  
  .char7 {
    transform: rotate(-32deg);
    left: 82px;
    top: 9px;
  }
  
  .char8 {
    transform: rotate(-17deg);
    left: 104px;
    top: 2px;
  }
  
  .char9 {
    transform: rotate(-8deg);
    left: 123px;
    top: -1px;
  }
  
  .char10 {
    transform: rotate(7deg);
    left: 143px;
    top: 0px;
  }
  
  .char11 {
    transform: rotate(13deg);
    left: 161px;
    top: 3px;
  }
  
  .char12 {
    transform: rotate(36deg);
    left: 184px;
    top: 18px;
  }
  
  .char13 {
    transform: rotate(45deg);
    left: 207px;
    top: 33px;
  }
  
  .char14 {
    transform: rotate(68deg);
    left: 224px;
    top: 54px;
  }
  
  .char15 {
    transform: rotate(68deg);
    left: 229px;
    top: 69px;
  }
  
  .char16 {
    transform: rotate(83deg);
    left: 234px;
    top: 89px;
  }
  
  .char17 {
    transform: rotate(90deg);
    left: 239px;
    top: 105px;
  }
  
  .char18 {
    transform: rotate(114deg);
    left: 235px;
    top: 133px;
  }
  
  .char19 {
    transform: rotate(114deg);
    left: 233px;
    top: 146px;
  }
  
  .char20 {
    transform: rotate(122deg);
    left: 222px;
    top: 157px;
  }

  .char22 {
    transform: rotate(143deg);
    left: 196px;
    top: 187px;
  }
  
  .char21 {
    transform: rotate(132deg);
    left: 211px;
    top: 173px;
  }
    
  .char23 {
    transform: rotate(152deg);
    left: 179px;
    top: 196px;
  }
  
  .char24 {
    transform: rotate(172deg);
    left: 154px;
    top: 206px;
  }
  
  .char25 {
    transform: rotate(178deg);
    left: 131px;
    top: 208px;
  }

  .char25d {
    transform: rotate(189deg);
    left: 112px;
    top: 207px;
  }

  .char26 {
    transform: rotate(213deg);
    left: 86px;
    top: 198px;
  }

  .char27 {
    transform: rotate(219deg);
    left: 79px;
    top: 190px;
  }

  .char28 {
    transform: rotate(220deg);
    left: 66px;
    top: 183px;
  }

  .char29 {
    transform: rotate(228deg);
    left: 50px;
    top: 171px;
  }

  .char30{
    transform: rotate(241deg);
    left: 44px;
    top: 157px;
  }

  .char31{
    transform: rotate(241deg);
    left: 30px;
    top: 142px;
  }

  .char32{
    transform: rotate(241deg);
    left: 24px;
    top: 127px;
  }
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="style.css">
    <title>Document</title>
</head>
<body>
    
<div class="contaner">

    <p id="corner"></p>
    <!-- <p>I want to bend my text around the circle.</p> -->

    <span class="char1">I</span>

    <span class="char2">w</span>
    <span class="char3">a</span>
    <span class="char4">n</span>
    <span class="char5">t</span>

    <span class="char6">t</span>
    <span class="char7">o</span>

    <span class="char8">b</span>
    <span class="char9">e</span>
    <span class="char10">n</span>
    <span class="char11">d</span>

    <span class="char12">m</span>
    <span class="char13">y</span>

    <span class="char14">t</span>
    <span class="char15">e</span>
    <span class="char16">x</span>
    <span class="char17">t</span>

    <span class="char18">a</span>
    <span class="char19">r</span>
    <span class="char20">o</span>
    <span class="char21">u</span>
    <span class="char22">n</span>
    <span class="char23">d</span>

    <span class="char24">t</span>
    <span class="char25">h</span>
    <span class="char25d">e</span>

    <span class="char26">c</span>
    <span class="char27">i</span>
    <span class="char28">r</span>
    <span class="char29">c</span>
    <span class="char30">l</span>
    <span class="char31">e</span>
    
    <span class="char32">.</span>

</div>

    



</body>

</html>

Upvotes: 3

cyrus
cyrus

Reputation: 134

There are 2 ways one with jquery in which you will slice each character and then arrange accordingly as shown above in example and second way is with css in which you will assign class to each character and than individually transform them like below code html

<div id="simple_arc">
  <span class='w0'>i</span>
  <span class='w1'></span>
  <span class='w2'>w</span>
  <span class='w3'>a</span>
  <span class='w4'>n</span>
  <span class='w5'>t</span>
  <span class='w6'></span>
  <span class='w7'>t</span>
  <span class='w8'>o</span>
  <span class='w9'></span>
 </div>

css

#simple_arc {
     display: block;
         width:306px;
         height:305px;
}

css for words

#simple_arc>span[class^=w]{
                     display:block;
                     position:absolute;
                     -moz-transform-origin:50% 100%;
                     -webkit-transform-origin:50% 100%;
                     -o-transform-origin:50% 100%;
                     -ms-transform-origin:50% 100%;
                     transform-origin:50% 100%;
                     }

#simple_arc span{

                     font-size:38px;
                     font-weight:regular;
                     font-style:normal;
                     line-height:0.65;
                     white-space:pre;
                     overflow:visible;
                     padding:0px;
                     }

#simple_arc .w0 {
                     -moz-transform: rotate(-1.14rad);
                     -webkit-transform: rotate(-1.14rad);
                     -o-transform: rotate(-1.14rad);
                     -ms-transform: rotate(-1.14rad);
                     transform: rotate(-1.14rad);
                     width: 21px;
                     height: 24px;
                     left: 42.7px;
                     top: 93.95px;
                     }

Upvotes: -2

Lester Vargas
Lester Vargas

Reputation: 368

What you are asking for is not easy. You need a function to 'fake it'. You can try this.

function writeInCircle(phrase, cx, cy, fontSize) {

  var d = $("<div>").addClass("writeInCircle").appendTo("body")

  var num = phrase.length
  var r = num * fontSize / 6

  $(d).css({
    position: "absolute",
    width: (2 * r) + "px",
    height: (2 * r) + "px",
    left: (cx - r) + "px",
    top: (cy - r) + "px"
  })
  for (var i = 0; i < num; i++) {
    var s = $("<span>").html(phrase.charAt(i)).appendTo(d)
    a = i / num * 2 * Math.PI
    var x = cx + r * Math.cos(a)
    var y = cy + r * Math.sin(a)
    $(s).css({
      "position": "absolute",
      left: x + "px",
      top: y + "px",
      "fontSize": fontSize
    })
    console.log(z.charAt(i) + " " + x + "," + y)
  }
}


z = "This is the text you need"
cx = 200
cy = 150
fontSize = 30
$(function() {
  writeInCircle(z, cx, cy, fontSize)
})

But what I would suggest is use an SVG. Thay would be more useful that recreating text in html and JS.

Upvotes: 1

Related Questions