Contenteditable высота перехода: анимировать после добавления (Shift+ Enter) и удаления строки текста

Пока работает на использование contenteditable атрибут на <div> тег с функцией автоматического роста текстового поля. Также высота перехода этого. Все это работает хорошо, за исключением одной вещи: удаление символов, а именно строки, не будет анимировать ее высоту, в отличие от добавления новых строк. У меня еще немного знаний по CSS.

.autogrow {
  border: 1px solid rgb( 0, 0, 0 );
  padding: 10px;
}
@keyframes line_insert {
  from {
    height: 0px;
  }
  to {
    height: 20px;
  }
}
.autogrow[contenteditable] > div {
  animation-duration: 250ms;
  animation-name: line_insert;
}
.autogrow[contenteditable] {
  overflow: hidden;
  line-height: 20px;
}
<div class="autogrow" contenteditable="true"></div>

Когда я нажимаю Shift + Enter, он тоже не анимируется, но хорошо работает при нажатии Enter. Проблема заключается в удалении строк и комбинации клавиш Shift + Enter при вводе новой строки.

Как заставить это работать? Можно ли это сделать с использованием чистого CSS? Или добавить функцию JavaScript для него?

2 ответа

Решение

Чтобы избежать этих проблем, я лично использую решение, не основанное на чистых CSS-анимациях / переходах, которые, как я обнаружил, всегда имеют проблемы. Например, в вашей реализации CSS существует эффект возврата, если вы слишком быстро используете Enter (вы можете замедлить анимацию, чтобы лучше ее увидеть).

Эффект возврата

Более того, обработка новых строк в разных браузерах отличается, некоторые добавят <div><br></div>, некоторые версии IE добавляют только <br>, так далее.

Мне никогда не удавалось исправить все эти проблемы или я нашел реализацию, исправляющую все это, поэтому я решил вообще не изменять поведение contenteditable Пусть браузер делает магию, которая работает и реагирует на происходящее.

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

Вместо этого я выбрал 2 элемента: один для фактического contenteditable и один для укладки моего contenteditable который будет иметь анимацию / переходы высоты, основанные на фактической высоте contenteditable,

Для этого я отслеживаю все события, которые могут изменить высоту contenteditable и если высота моего элемента стиля не одинакова, я анимирую элемент стиля.

var kAnimationSpeed = 125;
var kPadding = 10;

$('div[contenteditable]').on('blur keyup paste input', function() {
  var styleElement = $(this).prev();

  var editorHeight = $(this).height();
  var styleElementHeight = styleElement.height();

  if (editorHeight !== styleElementHeight - kPadding * 2) {
    styleElement.stop().animate({ height: editorHeight + kPadding * 2 }, kAnimationSpeed);
  }
});
.autogrowWrapper {
  position: relative;
}

.autogrow {
  border: 1px solid rgb(0, 0, 0);
  height: 40px; /* line-height + 2 * padding */
}

div[contenteditable] {
  outline: none;
  line-height : 20px;
  position: absolute;
  top: 10px; /* padding */
  left: 10px; /* padding */
  right: 10px; /* padding */
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="autogrowWrapper">
  <div class="autogrow"></div>
  <div contenteditable="true"></div>
</div>

Это вроде хаки, но это работает.

Во-первых, измените свой CSS

.autogrow {
  border: 1px solid rgb( 0, 0, 0 );
  padding: 10px;
}
@keyframes line_insert {
  from {
    height: 0px;
  }
  to {
    height: 20px;
  }
}
.autogrow[contenteditable] > div {
  animation-duration: 250ms;
  animation-name: line_insert;
}
.autogrow[contenteditable] {
  overflow: hidden;
  line-height: 20px;
}

Затем добавьте этот jQuery, который обнаруживает события Shift + Enter и добавляет div, когда они происходят.

$(".autogrow").keydown(function(e){

    if (e.keyCode == 13 && e.shiftKey || e.keyCode == 13)
    {
       $(this).animate({height: $(this).height()+20},200);
                $(this).append('<div><br></div>');
    }
});

И это должно работать.

Проверьте скрипку https://jsfiddle.net/wx38rz5L/582/

Другие вопросы по тегам