Нарисуйте диагональ внутри прямоугольника

, основанный на верхнем голосовом ответе С.Лотта (сент. 25, 08 в 21:43), но исправлен для небольших файлов.

def tail(the_file, lines_2find=20):  
    the_file.seek(0, 2)                         #go to end of file
    bytes_in_file = the_file.tell()             
    lines_found, total_bytes_scanned = 0, 0
    while lines_2find+1 > lines_found and bytes_in_file > total_bytes_scanned: 
        byte_block = min(1024, bytes_in_file-total_bytes_scanned)
        the_file.seek(-(byte_block+total_bytes_scanned), 2)
        total_bytes_scanned += byte_block
        lines_found += the_file.read(1024).count('\n')
    the_file.seek(-total_bytes_scanned, 2)
    line_list = list(the_file.readlines())
    return line_list[-lines_2find:]

    #we read at least 21 line breaks from the bottom, block by block for speed
    #21 to ensure we don't get a half line

Надеюсь, это полезно.

2
задан sylvain 19 March 2019 в 12:27
поделиться

2 ответа

Итак, ваша проблема заключается в том, как вы управляете изменением выбора type.

var p =  new CanvasState(document.getElementById('mainCanvas'),type);

Каждый раз, когда вы меняете выбор, вы создаете новый CanvasState, в который вы добавляете EventListener. Дело в том, что вы никогда не удаляете эти EventListener, и вы явно не удаляете свой предыдущий CanvasState.

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

Вы можете легко решить эту проблему, создав метод setType(newType) в CanvasState для вызова его в функции changeHandler.

Затем вы должны создать свой CanvasState вне этой функции и сохранить ссылку на него, чтобы вы могли вызвать myCanvas.setType(newType).

РЕДАКТИРОВАТЬ:

Более «современным» решением было бы извлечь функцию обработки из ваших вызовов addEventListener как метод, подобный:

handleMouseUp(event, type) {
  // Here your code for mouseUp
  // Edit the references to use the fields from "this"
}
[1121 И затем вы можете добавить их как:

canva.addEventListener("mouseup", (e) => this.handleMouseUp(e, this.type), true);

Таким образом, вы не ограничены средой eventListener / canvas «this», но можете получить доступ ко всем полям, которые вы установили для CanvasState. [1122 ]

0
ответ дан BreakBB 19 March 2019 в 12:27
поделиться

Я не хочу использовать кредит ответа, приведенного выше Сильвеном . Это как раз основная причина проблемы. Я уже проголосовал за его ответ. Вторая проблема связана с типом глобальной переменной. Внутри обработчиков событий вы используете тип глобальной переменной, которая по умолчанию объявлена ​​как строка. И ваш метод setType устанавливает тип CanvasState. Поэтому я внес изменения соответственно. Вы можете сослаться на них ниже. С этим связана другая проблема: если вы не выберете переключатель, вы все равно сможете нарисовать линию.

Если вы хотите немного поэкспериментировать, вы можете явно удалить обработчики событий, используя removeEventListner Это будет забавное упражнение.

Еще одна опция - вы можете заменить div mainCanvas, клонировав его без клонирования его обработчиков событий.

clone = div.cloneNode(false);// setting false will not clone child element and event handlers. 

Но это может добавить отставание при рисовании новой формы.

var storedLines = [];
var startX = 0;
var startY = 0;
var isDown;
var type = "line"; // current type

class CanvasState{
  // **** First some setup! ****
 constructor(canvas){
  this.canvas = canvas;
  this.type = type;
  this.width = canvas.width;
  this.height = canvas.height;
  this.ctx = canvas.getContext('2d');
  var offsetX = canvas.offsetLeft;
  var offsetY = canvas.offsetTop;
  this.valid = false; // when set to false, the canvas will redraw everything
  this.shapes = [];  // the collection of things to be drawn
  this.dragging = false; // Keep track of when we are dragging
  this.selection = null;
  this.dragoffx = 0; // See mousedown and mousemove events for explanation
  this.dragoffy = 0;
  var myState = this;
  this.selectionColor = '#CC0000';
  this.selectionWidth = 2;  
  var that = this;
  

  canvas.addEventListener('selectstart', function(e) { e.preventDefault(); return false; }, false);
  // Up, down, and move are for dragging
  canvas.addEventListener('mousedown', function(e) {
    e.preventDefault();
    e.stopPropagation();

    canvas.style.cursor = "crosshair";

    var mouseX = parseInt(e.clientX - offsetX);
    var mouseY = parseInt(e.clientY - offsetY);

    isDown = true;
    startX = mouseX;
    startY = mouseY;
  }, true);
  canvas.addEventListener('mousemove', function(e) {
    e.preventDefault();
    e.stopPropagation();
    var ctx = canvas.getContext('2d');
    if (!isDown) return;

    myState.redrawStoredLines();

    var mouseX = parseInt(e.clientX - offsetX);
    var mouseY = parseInt(e.clientY - offsetY);

    if(that.type == "rect"){
        ctx.beginPath();
        ctx.rect(startX, startY, mouseX - startX, mouseY - startY);
        ctx.stroke();
    }
    if(that.type == "line"){
        ctx.beginPath();
        ctx.moveTo(startX, startY);
        ctx.lineTo(mouseX, mouseY);
        ctx.stroke();
    }

  }, true);
  canvas.addEventListener('mouseup', function(e) {
    
      canvas.style.cursor = "default";
     
    e.preventDefault();
    e.stopPropagation();

    isDown = false;
    
    var mouseX = parseInt(e.clientX - offsetX);
    var mouseY = parseInt(e.clientY - offsetY);

    storedLines.push({
        type: that.type,
        x1: startX,
        y1: startY,
        x2: mouseX,
        y2: mouseY
    });
    console.log(storedLines);
    myState.redrawStoredLines();
  
  }, true);

canvas.addEventListener('handleMouseOut', function(e) {
    
      e.preventDefault();
    e.stopPropagation();
    
    if (!isDown) return;

    isDown = false;
    
    var mouseX = parseInt(e.clientX - offsetX);
    var mouseY = parseInt(e.clientY - offsetY);

    storedLines.push({
        type: that.type,
        x1: startX,
        y1: startY,
        x2: mouseX,
        y2: mouseY
    });

    myState.redrawStoredLines();
  

  }, true);
  
  
}
setType(newtype){
  if ( newtype === 'line' ) {
    this.type = "line";
    
   } 
   if ( newtype === 'rect' ) {
      this.type = "rect";
     console.log('settype:' + this.type);
   }  
}

 

 redrawStoredLines() {

    
    var ctx = this.canvas.getContext('2d');
    ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);

    if (storedLines.length == 0) return;

    // redraw each stored line
    for (var i = 0; i < storedLines.length; i++) {
        if(storedLines[i].type === "line"){
            ctx.beginPath();
            ctx.moveTo(storedLines[i].x1, storedLines[i].y1);
            ctx.lineTo(storedLines[i].x2, storedLines[i].y2);
            ctx.stroke();
        }
        if(storedLines[i].type === "rect"){
            ctx.beginPath();
            ctx.rect(storedLines[i].x1, storedLines[i].y1, 
                storedLines[i].x2 - storedLines[i].x1, storedLines[i].y2 - storedLines[i].y1);
            ctx.stroke();
        }
    }
}

}

var radios = document.querySelectorAll('input[type=radio][name="shape"]');

function changeHandler(event) {
  
    console.log(event.srcElement.value);
    mycanvas.setType(event.srcElement.value);
   
  
}

Array.prototype.forEach.call(radios, function(radio) {
   radio.addEventListener('change', changeHandler);
  
});


var mycanvas =  new CanvasState(document.getElementById('mainCanvas'));
body{
    font-family: Arial, Helvetica, sans-serif;
    font-weight: 16px;
}

.container{
    margin: 10px;
    padding: 2px;
    border: solid 1px black;
    background-color: #505050 
}

h3{
    margin: 10px;
    padding: 2px;
}

.toolbox{
    display: inline;
    list-style-type: none;    
}

.toolbox > li{
    display: inline-block;
    margin: 0;    
    vertical-align: middle;
}

div.sliders div{
    /*margin-top: 20px;    */
    display: inline-block;
}

.in-line p{
    font-size: 14px;
    display: block;
}

.in-line input{
    margin: 5px;
    display: block;
}


#square{
    margin-top: 20px;
    margin-left: 48%;
    width: 50px;
    height: 50px;
    background-color: rgb(127, 127, 127);
}

#rgbcolor{
    font-size: 14px; 
    text-align: center;   
}

#clearbtn{
    width: 50px;
    margin-left: 48%;
    margin-top: 10px;
}

.canvas{    
    margin: 10px;
    position: relative;    
    width: 600px;
    height: 400px;
    border: solid 1px black;
    background-color: #ffffff;
    cursor: crosshair;    
}

#coords{
    text-align: center;
}
<div class="container">
    <h3>Drawing Shapes</h3> 
    <div>
        <ul class="toolbox">
            <li id="btns">
              <div>        
            
                <input type="radio" name="shape" id="line" value="line">Line<br>
               
                <input type="radio" name="shape" id="rect" value="rect">Rectangle<br>                
              </div>
               
            <li id="cnvs">
          <div>
            <canvas id="mainCanvas" class="canvas" width="600" height="400"></canvas>  
            <h3 id="coords">(X, Y) : (0 , 0)</h3>
          </div> 
        </li>
          </ul>
    </div>                                                         
  </div>

0
ответ дан Rahul Raut 19 March 2019 в 12:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: