Временная шкала на html

306
08 апреля 2019, 21:20

Как реализовать подобную шкалу времени на html с добавлением 'красных участков'

Была идея сделать для каждого часа свой прогресс бар. Для заполнения определять по часу прогресс бар и просто убирать час, а минуты использовать как проценты

На bootstrap получилось сделать что-то подобное(Закинул на jsfiddle, внутри SO не работает)

На сколько это 'правильная' реализация?

Шкала нужна для вывода планов на день

Есть таблица с планами, в ней есть столбцы date_start и date_finish

Дата храниться подобным образом 2018-11-09 10:00:00

Выбираем желаемую дату и смотрим, что на эту дату запланировано. Простой вывод сделан(на скрине справа). На скрине шкала не подключена(Тестирую)

UPD ---

Во что у меня получилось:

Контроллер:

  $rez = Plan::whereDate('date_start', '>=', $plan_day)
                ->whereDate('date_start', '<=', $plan_day)
                ->get();//Достаем планы за определенное число
  foreach ($rez as $item) {
    $date_start_h = date("H", strtotime($item->date_start));
    $date_finish_m = date("i", strtotime($item->date_finish));
    if($date_start_h == 9) {
      $progress['nine'][] = ($date_finish_m*100)/60;
    } else if($date_start_h == 10) {
      $progress['ten'][] = ($date_finish_m*100)/60;
    } else if($date_start_h == 11) {
      $progress['eleven'][] = ($date_finish_m*100)/60;
    } else if($date_start_h == 12) {
      $progress['twelve'][] = ($date_finish_m*100)/60;
    } else if($date_start_h == 13) {
      $progress['thirteen'][] = ($date_finish_m*100)/60;
    } else if($date_start_h == 14) {
      $progress['fourteen'][] = ($date_finish_m*100)/60;
    } else if($date_start_h == 15) {
      $progress['fifteen'][] = ($date_finish_m*100)/60;
    } else if($date_start_h == 16) {
      $progress['sixteen'][] = ($date_finish_m*100)/60;
    } else if($date_start_h == 17) {
      $progress['seventeen'][] = ($date_finish_m*100)/60;
    }
  }
  $v['progress'] = $progress;
  return $v;

Вывод (planDay.progress равен $v['progress'] из контроллера):

<div class="row">
  <div class="col" style="padding-right: 0;">
    <div>9:00</div>
    <div class="progress progress-plan">
      <template v-for="nine in planDay.progress.nine">
        <div class="progress-bar progress-bar-striped bg-info" role="progressbar" :style="'width:'+nine+'%'" aria-valuenow="15" aria-valuemin="0" aria-valuemax="100"></div>
      </template>
    </div>
  </div>
  <div class="col" style="padding: 0">
    <div>10:00</div>
    <div class="progress progress-plan">
      <template v-for="ten in planDay.progress.ten">
        <div class="progress-bar progress-bar-striped bg-info" role="progressbar" :style="'width:'+ten+'%'" aria-valuenow="15" aria-valuemin="0" aria-valuemax="100"></div>
      </template>
    </div>
  </div>
  <div class="col" style="padding: 0">
    <div>11:00</div>
    <div class="progress progress-plan">
      <template v-for="eleven in planDay.progress.eleven">
        <div class="progress-bar progress-bar-striped bg-info" role="progressbar" :style="'width:'+eleven+'%'" aria-valuenow="15" aria-valuemin="0" aria-valuemax="100"></div>
      </template>
    </div>
  </div>
  <div class="col" style="padding: 0">
    <div>12:00</div>
    <div class="progress progress-plan">
      <template v-for="twelve in planDay.progress.twelve">
        <div class="progress-bar progress-bar-striped bg-info" role="progressbar" :style="'width:'+twelve+'%'" aria-valuenow="15" aria-valuemin="0" aria-valuemax="100"></div>
      </template>
    </div>
  </div>
  <div class="col" style="padding: 0">
    <div>13:00</div>
    <div class="progress progress-plan">
      <template v-for="thirteen in planDay.progress.thirteen">
        <div class="progress-bar progress-bar-striped bg-info" role="progressbar" :style="'width:'+thirteen+'%'" aria-valuenow="15" aria-valuemin="0" aria-valuemax="100"></div>
      </template>
    </div>
  </div>
  <div class="col" style="padding: 0">
    <div>14:00</div>
    <div class="progress progress-plan">
      <template v-for="fourteen in planDay.progress.fourteen">
        <div class="progress-bar progress-bar-striped bg-info" role="progressbar" :style="'width:'+fourteen+'%'" aria-valuenow="15" aria-valuemin="0" aria-valuemax="100"></div>
      </template>
    </div>
  </div>
  <div class="col" style="padding: 0">
    <div>15:00</div>
    <div class="progress progress-plan">
      <template v-for="fifteen in planDay.progress.fifteen">
        <div class="progress-bar progress-bar-striped bg-info" role="progressbar" :style="'width:'+fifteen+'%'" aria-valuenow="15" aria-valuemin="0" aria-valuemax="100"></div>
      </template>
    </div>
  </div>
  <div class="col" style="padding: 0">
    <div>16:00</div>
    <div class="progress progress-plan">
      <template v-for="sixteen in planDay.progress.sixteen">
        <div class="progress-bar progress-bar-striped bg-info" role="progressbar" :style="'width:'+sixteen+'%'" aria-valuenow="15" aria-valuemin="0" aria-valuemax="100"></div>
      </template>
    </div>
  </div>
  <div class="col" style="padding-left: 0">
    <div>17:00</div>
    <div class="progress progress-plan">
      <template v-for="seventeen in planDay.progress.seventeen">
        <div class="progress-bar progress-bar-striped bg-info" role="progressbar" :style="'width:'+seventeen+'%'" aria-valuenow="15" aria-valuemin="0" aria-valuemax="100"></div>
      </template>
    </div>
  </div>
</div>
</div>

Вот что получилось на скрине:

Появилось несколько проблем:

1)Не учтена дата начала, на скрине это Элегант, дата начала с 12:20 до 12:30 - на шкале он не учитывает 12:20, отсчет начинает с начала и до 30

2)Выделения на шкале используют 100 процентов, для выделения я использую минуты, максимальное значение в минутах это 60. Получается если будет например с 12:00 до 12:50, на шкале это будет 50% хотя 83% Перевел минуты в проценты (минуты*100)/60

3)Если план будет с 12:00 до 13:00 все сломается

4)Как-то слишком много кода

Answer 1

Так как рабочих решений на html+css выдвинуто не было, предлагаю решение на canvas

const time = { 
  "11:00": [ 
    [0, 20], 
    [40, 60] 
  ], 
  "12:00": [ 
    [10, 20], 
    [30, 40], 
    [50, 60] 
  ], 
  "13:00": [ 
    [0, 60] 
  ], 
  "14:00": [], 
  "15:00": [], 
  "16:00": [ 
    [25, 47] 
  ] 
}; 
window.addEventListener('resize', () => timeLine(time, "c")); 
timeLine(time, "c") 
 
function timeLine(time, canvasID) { 
  const canvas = document.getElementById(canvasID); 
  const c = canvas.getContext('2d'); 
 
  const num = Object.keys(time).length; 
 
  const img = document.createElement("img"); 
  img.src = "https://image.ibb.co/eH3VCA/img-2018-11-22-18-03-12.png"; 
  img.onload = function() { 
    const ptrn = c.createPattern(img, 'repeat'); // Create a pattern with this image, and set it to "repeat". 
 
    c.canvas.width = parseInt(getComputedStyle(canvas).width); 
    c.canvas.height = parseInt(getComputedStyle(canvas).height); 
 
    c.font = "10px Comic Sans MS"; 
    c.lineWidth = 1; 
    c.strokeStyle = "black"; 
 
 
 
    const unitWidth = c.canvas.width / num; 
    const tlh = c.canvas.height - 20; // tlh = timeline height 
 
    let i = 0; 
    for (let t in time) { 
      if (time[t].length !== 0) { 
        c.fillStyle = ptrn; 
        time[t].forEach((it) => { 
          c.fillRect(unitWidth * i + unitWidth / 60 * it[0], "0", unitWidth / 60 * (it[1] - it[0]), tlh); 
        }) 
      } 
 
      c.fillStyle = 'green'; 
      c.fillText(t, unitWidth * i, (2 * tlh + 20) / 2); 
      i++; 
    } 
 
    //Draw vertical lines 
    for (i = 0; i <= num; i++) { 
      let x = unitWidth * i; 
      // Check the first and last lines; 
      x = x === 0 ? c.lineWidth / 2 : i === num ? (c.canvas.width - c.lineWidth / 2) : x; 
 
      c.beginPath(); 
      c.moveTo(x, 0); 
      c.lineTo(x, tlh); 
      c.stroke(); 
 
    } 
    // Top and bottom lines 
    c.beginPath(); 
    c.moveTo(c.lineWidth / 2, c.lineWidth / 2); 
    c.lineTo(c.canvas.width, c.lineWidth / 2); 
 
    c.moveTo(c.lineWidth, tlh - c.lineWidth / 2); 
    c.lineTo(c.canvas.width, tlh - c.lineWidth / 2); 
    c.stroke(); 
  } 
}
canvas { 
  width: 100%; 
  height: 70px; 
}
<canvas id="c"></canvas>

READ ALSO
Как исправить баг в гуглхроме при использовании border-radius?

Как исправить баг в гуглхроме при использовании border-radius?

подскажите пожалуйста как исправить баг в хроме

207
Не работает скролл в таблице

Не работает скролл в таблице

Как можно реализовать scroll контента в Desktop версии на каждой вкладке в pop-up? В мобильной версии (media query) вкладки пропадают и все вливается в одну...

218
Как убрать рамку в input при вводе символов

Как убрать рамку в input при вводе символов

Подскажите, как убрать эту рамку как на изображении после клика мыши? Focus border none пробовал

217
Как сделать блок изображений в виде колоды карт?

Как сделать блок изображений в виде колоды карт?

Есть,допустим, блок с изображениями

202