Подтвердить что ты не робот

Создание формы снежинки, содержащей текст в форме

Я пытаюсь создать снежинки на своей веб-странице в течение зимнего сезона.

Первое, что я пробовал, это создать его с помощью SVG:

введите описание изображения здесь

<h3>Koch Snowflake Frac</h3>
<svg viewBox="-5 -5 110 110" xmlns="http://www.w3.org/2000/svg">
  <polyline stroke="cornflowerblue" stroke-width="2" fill="rgba(255,255,255,0.5)" points="55 5, 
                    60 10, 
                    65 10, 
                    65 15,
                    70 20,
                    75 20,
                    80 15,
                    85 20,
                    90 20,
                    85 25,
                    90 30,
                    80 30,
                    75 35,
                    80 40,
                    90 40,
                    85 45,
                    90 50,
                    85 50,
                    80 55,
                    75 50,
                    70 50,
                    65 55,
                    65 60,
                    60 60,
                    55 65,
                    50 60,
                    45 60,
                    45 55,
                    40 50,
                    35 50,
                    30 55,
                    25 50,
                    20 50,
                    25 45,
                    20 40,
                    30 40,
                    35 35,
                    30 30,
                    20 30,
                    25 25,
                    20 20,
                    25 20,
                    30 15,
                    35 20,
                    40 20,
                    45 15,
                    45 10,
                    50 10,
                    55 5" />
  <foreignObject x="0" y="0" requiredExtensions="http://www.w3.org/1999/xhtml">

    <body xmlns="http://www.w3.org/1999/xhtml">
      <p>Here is a paragraph that requires word wrap</p>
    </body>
  </foreignObject>
</svg>
4b9b3361

Ответ 1

Воспроизвести с помощью этой демонстрации

На самом деле это довольно интересный вопрос, и придумать ответ было непросто.

Вопрос задает форму (в данном случае снежинку), которая будет масштабироваться, чтобы соответствовать тексту внутри нее. Мой первый совет - использовать изображение, а не пытаться создать форму с помощью CSS. Изображения намного легче сделать масштаб, и могут иметь более подробную информацию, а затем форму CSS.

Итак, давайте покажем, как мы можем это сделать.

Прежде всего, поскольку вы хотите, чтобы элемент масштабировался, чтобы соответствовать шрифту, нам нужно создать элемент display:inline-block. Это сделает его только таким же широким, как и контент, в отличие от block, который сделает его таким же широким, как и его родительский, и все же сможет установить высоту (которую вы не можете сделать с inline).

Далее, нам нужно сделать элемент с высотой такой же, как ширина. К счастью, в CSS есть трюк, который позволяет вам делать именно это. Заполнение элемента вычисляется на основе его ширины, поэтому, если вы установите нижнюю часть (или верхнюю часть) до 100%, она будет иметь ту же ширину, что и высота. (См. Этот отличный ответ SO для дальнейшей информации).

После этого это всего лишь вопрос о центрировании текста внутри снежинки, что может немного поиграть со значениями, соответствующими вашему семейству шрифтов.

Если вы хотите jsfiddle с кодом: JSFiddle Demo

Полноэкранная демонстрация JSFiddle

Протестировано в Chrome, FireFox, IE и Safari. Для некоторых семейств шрифтов

могут потребоваться незначительные корректировки,

.snowflake{
    display:inline-block;
      background:url("http://i.imgur.com/4M9MH1Q.png") scroll no-repeat center/contain;
    }
/*This is for setting the height the same as the width, a 1:1 ratio. more info http://www.mademyday.de/css-height-equals-width-with-pure-css.html#outer_wrap */
    .snowflake:after{
    	content: "";
    	display: block;
    	padding-top: 100%;
    }
    .snowflake span{
        display:inline-block;
        -webkit-transform: translateY(110%);
            -ms-transform: translateY(110%);
                transform: translateY(110%);
        width:100%;
        text-align:center;
       padding-top:20%;
      }
/*This part is ugly, but it is required to work in chrome or IE, you may have to change the char for different font types*/
 .snowflake span:before, .snowflake span:after{
     content:"aaa";
     visibility:hidden;
     opacity:0;
  }
        Font-size 12pt:
    <div class="snowflake" style="font-size:12pt;">
      <span>It Snowing!</span>
    </div>
    Font-size 24pt:
    <div class="snowflake" style="font-size:24pt;">
      <span>It Snowing!</span>
    </div>
    Font-size 48pt:
    <div class="snowflake" style="font-size:48pt;">
      <span>It Snowing!</span>
    </div>

Ответ 2

Мое решение использует часть SVG, часть HTML/CSS для создания требуемого эффекта.

Я использовал функцию calc() CSS3 вместе с единицами ширины и высоты на основе видовых экранов, которые затем дают ему требуемую отзывчивость.

Он выглядит намного лучше, если элемент имеет ширину выше 200 пикселей.

Код

.container {
  position: relative;
  overflow: auto;
  display: block;
  width: 50vw;
  height: 50vw;
}
.container svg {
  width: 100%;
  height: 100%;
  position: absolute;
}
p {
  position: absolute;
  z-index: 100;
  background: white;
  left: 17.5vw;
  top: 17.5vw;
  margin: 0;
  padding: 10px 0;
  width: 10vw;
  text-align: center;
  font-size: 2vw;
  border: 20px solid black;
}
@media screen and (min-width: 920px) {
  p {
    font-size: 3vw;
    width: 12.5vw;
  }
}
<div class="container">
  <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve" width="50%">
    <polygon id="christmas-snowflake-icon" points="441.535,346.644 373.955,307.624 438.697,290.354 431.342,262.782 338.967,287.424
284.535,255.999 339.49,224.271 431.299,249.242 438.787,221.705 374.311,204.168 441.535,165.356 427.266,140.644 359.686,179.66
377.1,114.956 349.545,107.541 324.697,199.861 270.27,231.285 270.27,167.831 337.797,100.809 317.695,80.554 270.27,127.624
270.27,50 241.732,50 241.732,128.036 194.404,80.604 174.203,100.76 241.732,168.438 241.732,231.286 186.779,199.558
162.498,107.565 134.906,114.847 151.957,179.455 84.732,140.644 70.465,165.356 138.045,204.373 73.303,221.645 80.66,249.218
173.035,224.574 227.465,255.999 172.51,287.727 80.701,262.758 73.211,290.293 137.688,307.832 70.465,346.644 84.732,371.356
152.312,332.337 134.898,397.042 162.457,404.459 187.303,312.137 241.732,280.711 241.732,344.169 174.203,411.191
194.307,431.446 241.732,384.376 241.732,462 270.27,462 270.27,383.964 317.598,431.396 337.797,411.24 270.27,343.562
270.27,280.712 325.223,312.439 349.502,404.435 377.094,397.15 360.043,332.545 427.268,371.356 "></polygon>
  </svg>
  <p>This is some text Now</p>
</div>

Ответ 3

Используя svg, мне удалось сделать почти отзывчивое решение

.box{
    display:inline-block;
    position:relative;
    width:300px;
    height:300px;
}

.box:after{
    position:absolute;
    content:"Some text";
    width:20%;
    height:20%;
    padding:5%;
    font-size:100%;
    left:calc(50% - 15%);
    top:calc(50% - 19%);
}
<div class="box">
		<svg viewBox="0 0 99.999997 100" height="100%" width="100%">
		  	<g transform="translate(0,-952.36216)" id="layer1">
		    <path id="path4701" d="m 23,959 5,-3 6,11 6,-11 6,0 -9,17 4,7 8,-14 7,13 4,-7 -7,-13 3,-5 7,13 6,-11 4,2 -6,11 12,0 3,5 -18,0 -4,8 16,0 -7,13 8,0.12 7,-13 6,0 -7,13 12,0 -0.12,6 -12,-0 5,11 -3,5 -9,-17 -8,0.12 8,14 -16,0 4,8 18,0 -3,5 -12,-0.06 6,11 -4,3 -6,-11 -7,13 -3,-5 7,-13 -4,-7 -7,14 -8,-14 -4,7 9,17 -6,0.12 -6,-11 -6,11 -4,-3 6,-11 -14,-0.12 3,-6 15,0.12 4,-8 -15,-0.063 7,-14 -8,0 -9,17 -3,-5 6,-11 -12,0 0,-6 12,-0.06 -7,-13 6,-0.12 7,13 8,0.06 -7,-13 15,0.06 -4,-8 -15,-0.06 -3,-5 14,-0.06 z" style="fill:#2ad4ff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/>
		  	</g>
		</svg>
	</div>

Ответ 4

Использование холста:

Снежинка также может быть создана программно, используя холст HTML5. Выполнение этого программного обеспечения позволяет лучше контролировать текст и постоянно держать его в контейнере. Я уверен, что этот метод можно преобразовать в его эквивалентную версию SVG, но более комфортно с Canvas.

Одним из недостатков использования Canvas является то, что результат не реагирует. При масштабировании он становится размытым. Единственный способ избежать этого - перерисовать форму еще раз, когда есть изменение в текстовых (или) размерах и т.д.


Строительство

Форма фактически состоит из трех частей, и они выглядят следующим образом:

  • Внутренняя звезда с 6 шипами (зеленая звезда)
  • Линии (красные)
  • Наружная звезда с 6 шипами (синяя звезда)

введите описание изображения здесь

Звезды рисуются с использованием того же подхода, что и описанного в моем ответе здесь. В основном мы назначаем внутренний и внешний радиус каждому из них, находим точки на внутреннем и внешнем круге, а затем соединяем их попеременно, чтобы произвести звезду.

Линии также рисуются с использованием аналогичного подхода, за исключением того, что он имеет только один радиус, а линии выводятся из точек на (мнимой) внутренней окружности зеленой звезды на определенные точки на круге.

Вычисление размеров: Поскольку текст должен быть помещен в форму и форма должна расширяться, чтобы соответствовать тексту, первый шаг, который необходимо выполнить, - это вычислить width, который текст требует. Это делается с помощью measureText().width. Полученное значение задается как радиус окружности зеленой звезды (потому что текст должен оставаться внутри него).

Наконец, поскольку внешняя синяя звезда должна выглядеть так, как будто она похожа на обрезанный (не отображается полностью), height и width меньше, чем у внешнего радиуса голубой звезды, и a border-radius назначенный элементу холста.

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d"),
  spikes = 6,
  step = Math.PI / spikes,
  rot; /* no. of spikes for the stars */

function drawSnowFlake(content, font) {

  ctx.font = font; /* font of the text */

  /* get width required to fit text and set radius of each star */
  var text = ctx.measureText(content);
  innerRadius = (text.width / 2) * 1.15; /* extra factor is to leave gap between text and shape */
  outerRadius = text.width;

  /* set center point for the individual parts of the shape */
  x = leftOffset = outerRadius * 1.5;
  y = topOffset = outerRadius * 1.5;

  /* canvas height and width should be set same as the largest star for clip */
  canvas.height = outerRadius * 3;
  canvas.width = outerRadius * 3;

  /* default settings */
  rot = Math.PI / 2 * 3;
  ctx.beginPath();
  ctx.lineWidth = 15; /* thickness of the lines */
  ctx.strokeStyle = 'blue'; /* color of the lines */
  ctx.font = font; /* font of the text */

  /* create the inner star */

  ctx.moveTo(leftOffset, topOffset - outerRadius)
  for (i = 0; i < spikes; i++) {
    x = leftOffset + Math.cos(rot) * outerRadius;
    y = topOffset + Math.sin(rot) * outerRadius;
    ctx.lineTo(x, y);
    rot += step;

    x = leftOffset + Math.cos(rot) * innerRadius;
    y = topOffset + Math.sin(rot) * innerRadius;
    ctx.lineTo(x, y);
    rot += step;
  }
  ctx.lineTo(leftOffset, topOffset - outerRadius);
  ctx.closePath();
  ctx.stroke();
  ctx.restore();

  /* draws the outer star */
  ctx.beginPath();
  ctx.moveTo(leftOffset, topOffset - (outerRadius * 1.725));
  for (i = 0; i < spikes; i++) {
    x = leftOffset + Math.cos(rot) * (outerRadius * 1.725);
    y = topOffset + Math.sin(rot) * (outerRadius * 1.725);
    ctx.lineTo(x, y)
    rot += step

    x = leftOffset + Math.cos(rot) * (outerRadius * 1.15);
    y = topOffset + Math.sin(rot) * (outerRadius * 1.15);
    ctx.lineTo(x, y);
    rot += step;
  }
  ctx.lineTo(leftOffset, topOffset - (outerRadius * 1.725));
  ctx.closePath();
  ctx.stroke();
  ctx.restore();

  /* draws the lines from the stars */
  rot = Math.PI / 3;
  ctx.beginPath();
  for (i = 0; i < spikes; i++) {
    x = leftOffset + Math.cos(rot) * innerRadius;
    y = topOffset + Math.sin(rot) * innerRadius;
    x2 = leftOffset + Math.cos(rot) * (outerRadius * 1.5);
    y2 = topOffset + Math.sin(rot) * (outerRadius * 1.5);
    ctx.moveTo(x, y);
    ctx.lineTo(x2, y2);
    rot += 2 * Math.PI / spikes;
  }
  ctx.closePath();
  ctx.stroke();

  /* add text and position it */
  ctx.textBaseline = "middle";
  ctx.textAlign = "center";
  ctx.fillText(content, leftOffset, topOffset);
}

document.getElementById('draw').addEventListener('click', function() {
  var input = document.getElementById('content').value;
  var fontsize = document.getElementById('fontsize').value;
  var fontname = document.getElementById('fontname').value;
  drawSnowFlake(input, fontsize + "px " + fontname);
});

drawSnowFlake("TEXT HERE", "16px Arial");
div {
  margin-bottom: 10px;
}
canvas {
  border-radius: 50%;
}
<div class='controls'>
  <input id='content' type='textbox' value='TEXT HERE' />
  <select id='fontsize'>
    <option value='10'>10px</option>
    <option value='12'>12px</option>
    <option value='14'>14px</option>
    <option value='16' selected>16px</option>
  </select>
  <select id='fontname'>
    <option value='Arial' selected>Arial</option>
    <option value='Verdana'>Verdana</option>
    <option value='Courier'>Courier</option>
  </select>
  <button id='draw'>Draw</button>
</div>
<canvas id='canvas'></canvas>

Ответ 5

OP хотел, чтобы снежинка масштабировалась, чтобы соответствовать размеру текста. Большинство других ответов делают это наоборот.

Здесь самое простое решение, которое я мог бы поднять. Это в основном просто HTML и SVG с небольшим фрагментом JS. Это необходимо, потому что я не считаю возможным, чтобы шкала SVG соответствовала родительскому объекту, который не имеет явного размера.

Измените текстовое содержимое или стиль CSS внутреннего <div> на содержание вашего сердца, а снежинка SVG будет масштабироваться, чтобы соответствовать.

Вы почти наверняка покончили бы с JS, если бы вы были счастливы использовать фоновое изображение растрового изображения вместо SVG.

$().ready(function() {
  divWidth = $(".snowflake div").outerWidth();
  $(".snowflake svg").css("width", divWidth + "px");
});
.snowflake
{
  display: inline-block;
  position: relative;
}

.snowflake svg
{
  position: absolute;
  fill: #eef;
}

.snowflake DIV
{
  position: absolute;
  padding: 100px;
  font: 30pt sans-serif;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="snowflake">

  <svg viewBox="2 0 32 36">
    <path d="M33.212,26.16l-3.054-1.764l1.84-1.062c0.238-0.139,0.32-0.441,0.184-0.684c-0.14-0.238-0.445-0.322-0.684-0.183 L29.16,23.82l-2.32-1.34l4.729-2.73c0.239-0.139,0.321-0.441,0.184-0.684c-0.139-0.238-0.445-0.322-0.684-0.183l-5.23,3.019 l-3.619-2.09l4.352-1.918l-4.354-1.919l3.619-2.091l5.231,3.021c0.079,0.047,0.165,0.067,0.25,0.067 c0.174,0,0.342-0.091,0.435-0.25c0.139-0.239,0.057-0.546-0.184-0.683l-4.731-2.732l2.32-1.34L31.5,13.32 c0.079,0.046,0.165,0.066,0.25,0.066c0.173,0,0.341-0.09,0.435-0.25c0.138-0.238,0.056-0.545-0.184-0.682L30.16,11.39l3.052-1.762 c0.239-0.139,0.32-0.443,0.184-0.684c-0.14-0.238-0.446-0.322-0.684-0.184l-3.051,1.763L29.66,8.401c0-0.275-0.225-0.5-0.5-0.5 c-0.276,0-0.5,0.225-0.5,0.5l0.001,2.699l-2.32,1.34l0.001-5.46c0-0.276-0.224-0.5-0.5-0.5c-0.275,0-0.5,0.224-0.5,0.5 l-0.001,6.037l-3.619,2.09l0.515-4.728l-3.838,2.81V9.008l5.229-3.021c0.238-0.138,0.32-0.443,0.184-0.684 c-0.14-0.238-0.445-0.321-0.684-0.182l-4.729,2.73V5.173l2.339-1.352c0.239-0.138,0.321-0.443,0.184-0.684 c-0.14-0.238-0.445-0.322-0.684-0.182L18.399,4.02V0.5c0-0.276-0.224-0.5-0.5-0.5s-0.5,0.224-0.5,0.5v3.523L15.56,2.961 c-0.24-0.141-0.545-0.057-0.683,0.184c-0.138,0.239-0.056,0.545,0.183,0.684l2.339,1.352v2.678l-4.729-2.73 c-0.24-0.14-0.545-0.057-0.683,0.184c-0.138,0.239-0.056,0.545,0.183,0.684l5.229,3.02v4.184l-3.837-2.811l0.514,4.729 l-3.621-2.092V6.989c0-0.276-0.224-0.5-0.5-0.5c-0.276,0-0.5,0.224-0.5,0.5v5.462l-2.318-1.34L7.136,8.41 c0-0.277-0.224-0.5-0.5-0.5c-0.276,0-0.5,0.223-0.5,0.5l0.001,2.125L3.084,8.771C2.845,8.63,2.539,8.714,2.401,8.955 C2.263,9.194,2.345,9.5,2.584,9.638L5.636,11.4l-1.839,1.062c-0.239,0.139-0.321,0.443-0.183,0.684 c0.093,0.16,0.261,0.25,0.434,0.25c0.085,0,0.171-0.021,0.25-0.066l2.339-1.351l2.319,1.339l-4.729,2.73 c-0.239,0.139-0.321,0.443-0.183,0.684c0.093,0.16,0.261,0.25,0.434,0.25c0.085,0,0.171-0.021,0.25-0.066l5.23-3.021l3.622,2.091 l-4.352,1.919l4.351,1.919l-3.621,2.09l-5.231-3.018c-0.241-0.138-0.545-0.058-0.683,0.184c-0.138,0.24-0.056,0.545,0.183,0.686 l4.731,2.729l-2.321,1.34l-2.338-1.352c-0.239-0.142-0.545-0.058-0.683,0.184c-0.138,0.238-0.056,0.545,0.183,0.684l1.838,1.062 l-3.05,1.76c-0.239,0.139-0.321,0.443-0.183,0.684c0.093,0.16,0.261,0.25,0.434,0.25c0.085,0,0.171-0.021,0.25-0.065l3.051-1.763 L6.14,27.4c0,0.276,0.224,0.5,0.5,0.5l0,0c0.276,0,0.5-0.225,0.5-0.5l-0.001-2.701l2.322-1.34l-0.002,5.463 c0,0.277,0.224,0.5,0.5,0.5s0.5-0.223,0.5-0.5l0.002-6.041l3.619-2.09l-0.514,4.729l3.837-2.81v4.183l-5.228,3.021 c-0.239,0.139-0.321,0.442-0.183,0.684c0.138,0.236,0.444,0.318,0.683,0.184l4.728-2.73v2.679l-2.339,1.353 c-0.239,0.139-0.321,0.442-0.183,0.684c0.138,0.236,0.444,0.32,0.683,0.184l1.839-1.062V35.3c0,0.274,0.224,0.5,0.5,0.5 s0.5-0.226,0.5-0.5v-3.524l1.841,1.062c0.079,0.046,0.165,0.066,0.25,0.066c0.174,0,0.342-0.09,0.435-0.25 c0.139-0.239,0.057-0.545-0.184-0.684l-2.341-1.354v-2.678l4.729,2.73c0.079,0.046,0.165,0.066,0.25,0.066 c0.174,0,0.342-0.09,0.435-0.25c0.139-0.239,0.057-0.545-0.184-0.684l-5.229-3.021V22.6l3.838,2.811l-0.514-4.729l3.62,2.09v6.039 c0,0.276,0.224,0.5,0.5,0.5c0.275,0,0.5-0.224,0.5-0.5V23.35l2.318,1.34l0.001,2.699c0,0.275,0.225,0.5,0.5,0.5s0.5-0.225,0.5-0.5 l-0.001-2.123l3.053,1.764c0.079,0.045,0.165,0.066,0.25,0.066c0.174,0,0.342-0.09,0.435-0.25 C33.536,26.604,33.454,26.296,33.212,26.16z M20.997,23.259l-2.6-1.901l-0.499-0.363l-0.501,0.365l-2.598,1.9l0.348-3.201 l0.067-0.615l-0.567-0.25l-2.945-1.299l2.946-1.299l0.566-0.25l-0.067-0.616l-0.348-3.2l2.598,1.901l0.5,0.364l0.5-0.365l2.6-1.901 l-0.349,3.201l-0.066,0.616l0.564,0.249l2.946,1.3l-2.944,1.299l-0.566,0.25l0.066,0.615L20.997,23.259z"/>
  </svg>

  <div>Here is some text. It even wrapped.</div>

</div>