Анимация высоты Contenteditable: анимировать только после удаления строки

Это продолжение моего предыдущего вопроса.

Мне удалось исправить "паузы анимации при каждом нажатии клавиши", добавив условие e.which === 13, который обнаруживает и анимирует при нажатии клавиши Enter.


Вот как работает предыдущий:

Как вы можете видеть, после ввода новой строки и продолжения нажатий клавиш анимация отстает, что означает, что анимация выполняется при каждом нажатии клавиш.


Это модифицированный, который будет анимироваться только после нажатия Enter:

Работает плавно (правда, немного отстает во время записи).


Вот как это работает при удалении каждого символа (не долгое нажатие):

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


Так что сейчас я пытаюсь достичь обратного, плавно анимировать после удаления новой строки.

Вот живой код:

var kAnimationSpeed = 250;
var kPadding = 10;

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

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

  if (editorHeight !== styleElementHeight - kPadding * 2 && e.which === 13 || e.which === 8) {
    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>

Как можно добиться плавной анимации при удалении новой строки или как анимировать только при удалении новой строки?

2 ответа

Решение

Так что мне удалось решить проблему, основываясь на ответе Алекса.

В его ответе работает только при нажатии клавиши Enter. Но моя цель - использовать Shift + Enter. Нажатие Enter введет новый <div> внутри contenteditable div, в то время как Shift + Enter вставляет новый <br> вместо <div>, Поэтому я изменяю код, который будет рассчитывать <br> сохраняет значение в данные и сравнивает, меньше ли текущее число строк, чем новое количество строк, а также прослушивает клавишу Backspace. Затем я заменяю e.which === 8 с newLineDeleted переменная, чтобы сказать, когда новая строка удаляется. И удалить input функция, так что он будет возвращать точное логическое значение (потому что, кажется, не работает с input функция в нем. Я также добавляю слушателя.

var kAnimationSpeed = 250;
var kPadding = 10;

$('div[contenteditable]').on('blur keyup paste', function(e) {
  var styleElement = $(this).prev();
  var editorHeight = $(this).height();
  var styleElementHeight = styleElement.height();
  
  var lineCount = parseInt($(this).data('linecount') || 0);
  var newLineCount = $(this).children('br').length;
  $(this).data('linecount', newLineCount);
  var newLineDeleted = (lineCount - 1 === newLineCount && e.which === 8);
  
  var cutPasteListener = (e.ctrlKey && e.which === 86 || e.which === 88);

  if (editorHeight !== styleElementHeight - kPadding * 2 && e.which === 13 || newLineDeleted || cutPasteListener) {
    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>

Благодарю.

Я не знаю, работает ли это кроссбраузер, но Chrome добавляет <div>s для строк, так что вы можете посчитать их:

рабочая скрипка

var kAnimationSpeed = 250;
var kPadding = 10;
var keyCodeDelete = 8;
var keyCodeReturn = 13;

$('div[contenteditable]').on('blur keyup paste', function(e) {
  var el = $(this);
  var styleElement = el.prev();
  var editorHeight = el.height();
  var styleElementHeight = styleElement.height();

  var divCount = parseInt(el.data('divcount') || 0 );
  var newDivCount = el.children('div').not(':contains("br")').length;
  var newLineDeleted = (divCount - 1 == newDivCount && e.which == keyCodeDelete);

  var heightCheck = (editorHeight !== styleElementHeight - kPadding * 2);
  var keyCodeCheck = (e.which === keyCodeReturn || e.which === keyCodeDelete);


  if (heightCheck && keyCodeCheck) {
    if (newLineDeleted) {
      $('body').append('<p>nl removed!</p>');
    }
    styleElement.stop().animate({ height: editorHeight + kPadding * 2 }, kAnimationSpeed);
  }

  el.data('divcount', newDivCount);
});

Так что вам просто нужно настроить анимацию:)

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