Tôi đang cố gắng bắt chước dấu của một vùng văn bản với mục đích tạo ra một textarea có trọng lượng rất nhẹ. Tôi không muốn sử dụng một cái gì đó như codemirror hoặc bất kỳ thư viện lớn khác bởi vì tôi sẽ không sử dụng bất kỳ tính năng của họ.Bắt chước cẩn thận trong văn bản
Tôi có một <pre>
được đặt phía sau một vùng văn bản có nền trong suốt để tôi có thể mô phỏng hiệu ứng làm nổi bật trong văn bản. Tuy nhiên, tôi cũng muốn có thể thay đổi màu chữ (vì vậy nó không phải lúc nào cũng giống nhau). Vì vậy, tôi đã thử color: transparent
trên vùng văn bản cho phép tôi tạo kiểu văn bản theo bất kỳ cách nào tôi muốn bởi vì nó chỉ xuất hiện trên phần tử <pre>
phía sau vùng văn bản, nhưng dấu mũ sẽ biến mất.
Tôi đã làm cho nó hoạt động khá tốt, mặc dù nó không hoàn hảo. Vấn đề chính là khi bạn giữ một chìa khóa và thư rác nhân vật đó, các caret dường như luôn luôn tụt hậu một nhân vật phía sau. Không chỉ vậy, nó có vẻ là khá tài nguyên nặng ..
Nếu bạn thấy bất kỳ thứ gì khác trong mã cần được cải thiện, hãy bình luận về điều đó!
Dưới đây là một fiddle với mã: http://jsfiddle.net/2t5pu/25/
Và đối với bạn của những người không muốn đến thăm jsfiddle vì lý do gì, sau đây là toàn bộ mã:
CSS:
textarea, #fake_area {
position: absolute;
margin: 0;
padding: 0;
height: 400px;
width: 600px;
font-size: 16px;
font: 16px "Courier New", Courier, monospace;
white-space: pre;
top: 0;
left: 0;
resize: none;
outline: 0;
border: 1px solid orange;
overflow: hidden;
word-break: break-word;
padding: 5px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
}
#fake_area {
/* hide */
opacity: 0;
}
#caret {
width: 1px;
height: 18px;
position: absolute;
background: #f00;
z-index: 100;
}
HTML :
<div id="fake_area"><span></span></div>
<div id="caret"></div>
<textarea id="textarea">test</textarea>
JAVASCRIPT:
var fake_area = document.getElementById("fake_area").firstChild;
var fake_caret = document.getElementById("caret");
var real_area = document.getElementById("textarea");
$("#textarea").on("input keydown keyup propertychange click", function() {
// Fill the clone with textarea content from start to the position of the caret.
// The replace /\n$/ is necessary to get position when cursor is at the beginning of empty new line.
doStuff();
});
var timeout;
function doStuff() {
if(timeout) clearTimeout(timeout);
timeout=setTimeout(function() {
fake_area.innerHTML = real_area.value.substring(0, getCaretPosition(real_area)).replace(/\n$/, '\n\u0001');
setCaretXY(fake_area, real_area, fake_caret, getPos("textarea"));
}, 10);
}
function getCaretPosition(el) {
if (el.selectionStart) return el.selectionStart;
else if (document.selection) {
//el.focus();
var r = document.selection.createRange();
if (r == null) return 0;
var re = el.createTextRange(), rc = re.duplicate();
re.moveToBookmark(r.getBookmark());
rc.setEndPoint('EndToStart', re);
return rc.text.length;
}
return 0;
}
function setCaretXY(elem, real_element, caret, offset) {
var rects = elem.getClientRects();
var lastRect = rects[rects.length - 1];
var x = lastRect.left + lastRect.width - offset[0] + document.body.scrollLeft,
y = lastRect.top - real_element.scrollTop - offset[1] + document.body.scrollTop;
caret.style.cssText = "top: " + y + "px; left: " + x + "px";
//console.log(x, y, offset);
}
function getPos(e) {
e = document.getElementById(e);
var x = 0;
var y = 0;
while (e.offsetParent !== null){
x += e.offsetLeft;
y += e.offsetTop;
e = e.offsetParent;
}
return [x, y];
}
Xin cảm ơn trước!
Dấu sót của bạn bị trễ do dấu sót thực sự gây ra một chút thời gian nghỉ ngơi. Hãy thử nhập vài dòng văn bản và sau đó bấm và giữ nút chuột trái trên hàng khác nhau và bạn sẽ thấy nó. Để khắc phục điều này, bạn sẽ phải đặt độ mờ của vùng văn bản thành 0. Nhưng sau đó bạn sẽ phải xử lý văn bản hiển thị chính xác. – twil
bạn có thực sự cần cập nhật con trỏ 100 lần một giây không? tôi nghĩ rằng 5 hoặc 10 sẽ đủ. đó là lý do khiến ứng dụng của bạn chạy chậm ... – dandavis
@dandavis: cần phải đáp ứng như ứng dụng mặc định. –