# 新增可移動文字方塊與Html2Canvas區塊下載
###### codepen:https://codepen.io/liu_0821/pen/NWePBZQ

## 主要說明
1. 說明 `touchmove` 和 `mousemove` 的實際應用方式。
2. 當 `Html2Canvas` 遇到不支援的 CSS3 的解決方法。
3. 簡易的文字設定與套用方法。
## 部分HTML
```
<div class="col-12 selectGroup">
<select class="form-select" id="fontStyle">
... // 文字字型
</select>
<select class="form-select" id="fontSize">
... // 文字大小
</select>
<select class="form-select" id="fontWeight">
... // 文字粗細
</select>
<select class="form-select" id="fontOrientation">
... // 文字方向
</select>
</div>
<input type="text" class="col-12 inputText" placeholder="請輸入文字">
<div class="col-12 btnGroup">
<button class="col-12 btn btn-success" id="addText">新增</button>
</div>
<div class="moveGroup">
<button class="btn btn-danger" id="delete"> 刪除 </button>
<button class="btn btn-success" id="save"> 下載 </button>
<div class="col-12 touchDiv">
</div>
</div>
```
## 部分CSS
- `writing-mode` 不支援html2Canvas。
```
.moveDivText{ // 移動文字方塊
width: auto;
border:1px solid #ced4da;
border-radius: .375rem;
font-family:"serif";
font-size:18px;
font-weight: 500;
text-align: center;
position: absolute; // 設定可移動
cursor: move;
z-index: 0;
transform: scale(1);
left: 0;
top: 0;
padding: .375rem;
}
.moveDivText:active{ // 點選之後有紅框
opacity: .8;
border:2px solid #d13e3e;
}
.mixed{ // 文字方塊橫向
-webkit-writing-mode: horizontal-tb;
writing-mode: horizontal-tb;
text-orientation:mixed;
}
.upright{ // 文字方塊直向
// 解決方案
transform: rotate(0deg);
// html2Canvas 不支援的CSS樣式
/*
-webkit-writing-mode: vertical-lr;
writing-mode: sideways-rl; 中文垂直
text-orientation:upright; 英文垂直
*/
}
.chose{ // 被選取的樣式
opacity: .8;
border:2px solid #d13e3e;
}
```
## JS
### 建立文字方塊與設定文字屬性
- 由於html2Canvas不支援垂直屬性,在每個字中間穿插`</br>`換行,再利用`transform`屬性呈現出文字垂直的樣式
```
// 文字屬性
$("#fontStyle").on("change",(e)=>{
$('.inputText').css('font-family',$(e.target)val());
});
$("#fontSize").on("change",(e)=>{
$('.inputText').css('font-size',$(e.target).val() + "px");
});
$("#fontWeight").on("change",(e)=>{
$('.inputText').css('font-weight',$(e.target).val());
});
$("#addText").on('click',(e)=>{
// 未輸入文字會跳出去
if($(".inputText").val() =="" ){
return;
}
// 建立文字方塊
let div = document.createElement("div");
if($("#fontOrientation").val().includes("mixed")){
$(div).attr('class','moveDivText mixed');
$(div).text($('.inputText').val());
}else if($("#fontOrientation").val().includes("upright")){
$(div).attr('class','moveDivText upright');
// 穿插</br> 換行顯示出直向的感覺
let _inputValue = $('.inputText').val().split('').join('</br>');
$(div).html(_inputValue);
}
$(div).css('font-family',$("#fontStyle").val());
$(div).css('font-size',$("#fontSize").val() + "px");
$(div).css('font-weight',$("#fontWeight").val());
$(div).css('z-index',$(".touchDiv").find('.moveDivText').length);
$('.touchDiv').append(div);
move();
setTimeout((e)=>{
$('.inputText').val("");
},300);
});
```
### 觸控與滑鼠操作
```
let moveDiv = false; // 移動
function move(){
$('.moveDivText').each((i,dom)=>{
$('.moveDivText').removeClass('chose');
$(dom).click((e)=>{
$(e.target).addClass('chose');
clickMove($(e.target));
});
});
}
// 被選取的可移動
function clickMove(dom){
document.body.addEventListener('touchmove',function(e){e.preventDefault(); },false);
let doms = $(dom).[0];
let _text_scale = $(doms).css('transform');
let tr = _text_scale.split('(')[1].split(')')[0].split(',')
let scale =Math.sqrt(tr[0] * tr[0] + tr[1] * tr[1]); // 抓目前scale值
let store={
scale:Math.sqrt(tr[0] * tr[0] + tr[1] * tr[1])
};
doms.onmousedown = function (e) {
$('.moveDivText').removeClass('chose');
$(dom).addClass('chose');
moveDiv = true;
x = e.clientX - doms.offsetLeft;
y = e.clientY - doms.offsetTop;
// $(doms).addClass('chose');
document.onmousemove = function (e) {
if (!moveDiv) {
return;
}
doms.style.left = e.clientX - x + 'px';
doms.style.top = e.clientY - y + 'px';
// 按住左鍵才可以滾輪放大 / 縮小
doms.onmousewheel = (e) => {
if (!moveDiv) {
return;
}
if (e.wheelDelta > 0) {
scale += 0.04
if (scale > 3.5) {
scale = 3.5
}
} if (e.wheelDelta < 0) {
scale -= 0.04
if (scale < 0.75) {
scale = .75
}
}
$(doms).css('transform', 'scale(' + scale + ')');
};
document.onmouseup = function () {
moveDiv = false;
$(doms).removeClass('chose');
doms.onmousemove = null;
document.onmouseup = null;
};
}
}
// touch
doms.addEventListener('touchstart', function (event) {
$('.moveDivText').removeClass('chose');
$(event.target).addClass('chose');
moveDiv = false;
var touches = event.touches;
var events = touches[0];
var events2 = touches[1];
var x = doms.offsetLeft;
var y = doms.offsetTop;
console.log(events)
event.preventDefault();
// 擷取第1根手指座標
store.pageX = events.pageX;
store.pageY = events.pageY;
store.moveable = true;
store.x = x;
store.y = y;
if (events2) {
store.pageX2 = events2.pageX;
store.pageY2 = events2.pageY;
}
store.originScale = store.scale || 1;
});
doms.addEventListener('touchmove', function (event) {
if (!store.moveable) {
return;
}
event.preventDefault();
var touches = event.touches;
var events = touches[0];
var events2 = touches[1];
// 兩隻手指移動
if (events2) {
// 擷取第2根手指座標
if (!store.pageX2) {
store.pageX2 = events2.pageX;
}
if (!store.pageY2) {
store.pageY2 = events2.pageY;
}
// 獲取座標
var getDistance = function (start, stop) {
return Math.hypot(stop.x - start.x, stop.y - start.y);
};
// 雙指縮放比例計算
var zoom = getDistance({
x: events.pageX,
y: events.pageY
}, {
x: events2.pageX,
y: events2.pageY
}) /
getDistance({
x: store.pageX,
y: store.pageY
}, {
x: store.pageX2,
y: store.pageY2
});
// 應用在div上的比例
var newScale = store.originScale * zoom;
// 最小比例
if (newScale < .5) {
newScale = .5;
}
// 最大比例
if (newScale > 3) {
newScale = 3;
}
store.scale = newScale;
// 圖片縮放應用
doms.style.transform = 'scale(' + newScale + ')';
} else {
var moveX = events.pageX - store.pageX;
var moveY = events.pageY - store.pageY;
var imagetop = store.x + moveX;
var imageleft = store.y + moveY;
// console.log(imagetop,imageleft)
$(doms).css({ 'top': imageleft + 'px', 'left': imagetop + 'px' });
}
});
doms.addEventListener('touchend', function () {
$(event.target).addClass('chose');
store.moveable = false;
moveDiv = false;
delete store.pageX2;
delete store.pageY2;
});
doms.addEventListener('touchcancel', function (event) {
$(event.target).addClass('chose');
store.moveable = false;
moveDiv = false;
delete store.pageX2;
delete store.pageY2;
});
}
```
### 刪除被選取的元素
```
$('#delete').click((e)=>{
console.log(111)
$('.moveDivText').each((i,dom)=>{
console.log(dom)
if($(dom).attr('class').includes('chose')){
$(dom).remove();
return;
}
});
});
```
### Html2Canvas下載
- 關於這個套件的簡單說明可以看我另一篇文章唷~[點我查看](https://hackmd.io/@LindaLiu/S1VCu9B6n)
```
$('#save').click((e) => {
$('.moveDivText').css('border','none');
let dom =document.querySelector(".touchDiv");
html2canvas(dom,{
width:dom.clientWidth, //擷取畫面之寬高
height:dom.clientHeight,
scrollX:0,
scrollY:0,
useCORS:true,
allowTaint:true
}).then(function (canvas) {
a = document.createElement("a");
a.href = canvas.toDataURL("image/jpeg");
a.download = "我的檔案.jpeg";
a.click();
$('.moveDivText').css('border','1px solid #ced4da');
$('.touchDiv').find('div').remove();
});
});
```
---
##### ヽ(∀゚ )人(゚∀)人( ゚∀)人(∀゚ )人(゚∀)人( ゚∀)ノヽ(∀゚ )人(゚∀゚)人( ゚∀)人(∀゚ )人(゚∀゚)人( ゚∀)人(∀゚ )人( ゚∀)人
##### 以上 如果註解哪裡有錯誤或有問題,歡迎提出來一起討論~~~~